/*
 * Copyright (C) 2007, 2008, 2009 Windy Hill Technology
 *
 * This file is part of FT Table Opener.
 *
 * FT Table Opener is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FT Table Opener is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with FT Table Opener.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project Home: http://code.google.com/p/fttableopener/
 */




/*

FT Table Opener - Opens poker tables with specific criteria manually or automatically

Developers:
   Gary Muhonen (nanochip)

This software was inspired by Roland's original iWitness software and JukOfYork's Safe-Mine software. 
   Some routines in this software are routines from these two freeware software programs.

Special thanks to:    
   Roland, SamIAm _dave_, JukOfYork, and other AHK programmers for their great scripts.
   The developers of AutoHotKey, a wonderful "open source" programming language.
   The developers of scripts that have provided their code for others to learn from and re-use.


*********************************************************************************************************************

Version 1.15  8/30/09
1. FT Table Opener is converted to an open source software project, licensed under GNU General Public License (v3 or later)
2. Removed Registration tab and related code for registering this software

Version 1.14  5/2/2009
1. Fixed problem where the "Max Number Tables to Open" is reset back to 3 when you start the program.
2. Fixed problem where the number of open tables was not counted correctly if the user manally closed a table.

Version 1.13  4/28/09
1. Full Tilt changed the format of the data in their lobby in a new release, which prevented Table Opener from working correctly. Software was updated to support this new verion of the FT software.
2. Full Tilt added additional items to their "Type" column in there lobby and Table Opener now supports these new options (in the Table Options drop-down box).
3. Changed operation so that you can open tables with 0 or 1 players at the table.
4. Changed the program's icon.

gm changes that don't need to be announced.
3. Removed the onexit code near beginning.

Version 1.12  2/25/08
1. Fixed a labeling problem where Max # of Short Stacks was shown on the wrong criteria row (covering Min hands per hour)

Version 1.11  12/13/2008
1. Added "All" option to "Table Options" so that you can open either Deep stack or non-Deep stack tables within one group.
2. Added "unsupported feature" where 2 or more instances of FTTO can be run concurrently. This feature is not recommended because only one set of settings will be saved when you close the program and each instance
can possilby interfere with one another if they both try to open tables at the same time.

Version 1.10  11/09/2008
1. Added criteria "Max # Players", so that you can limit the number of players at tables you open. This is useful if want the software to open a number of tables with empty seats, so that you can easily find
tables that you can sit at.
2. Added a Closing Table Criteria called "Close tables not meeting Max # Players criteria". This is useful if you want to automatically close tables that fill up beyond your maximum desired number.
3. Added three additional times for the Timer Period: .25, .5, and .75 minutes, so that FTTO can be run very often when you are trying to find empty tables.
4. Add the item "1" to the "# Seats" drop down box. This allow special tables to be opened like the heads up "Ivey Deathmatch".

Version 1.08  7/9/08
1. Fixed problem where higher stakes tables were not opening correctly.

Version 1.07  7/1/08
1. Fixed problem where some "FT Lobby" names were not saved in the settings file (.ini) correctly. Then when the user restarted the program, the software
would not return to the previous setting.

My Notes:
1. Changed the variable name "DesiredGame" to "Desired Games" so that there would be a new variable saved in the users .ini file. This is
because I changed all the selection choices in the "Ft Lobby" drop down box.

Version 1.06  5/7/08
1. Added feature: There is a new Table Options box for selecting "deep stack" tables
2. Added support for the Happy Hour (smiley face) tables.
3. Added feature: There is a new closing table criteria checkbox to allow for closing of tables if they do not meet any of your selected table criteria (except number on wait list and number of short stacks).
4. Changed the software method by which tables are closed. This may solve a very infrequent problem were sometimes a table would not close if it was empty.  

Version 1.05  3/10/08
1. Changed the maximum allowed number of tables that can be opened to 18 (it was 16).
2. New Feature: Added the ability to NOT open tables if there are (too many) short stacks at the table. You can define how many Big Blinds is a short stack.
You can set a new criteria that defines the maximum number of short stacks that you will tolerate at a table to be opened. Set this to 0, and FTTO will not open a table
if there are 1 or more short stacks. Set it to 1, and the software will only open a table if there are 1 or fewer short stacks at the table. Set this
to 10, and the feature will be disabled (as you are willing to open tables with any number of short stacks at the table).
3. New Feature: You can define an "Avoid Players" list. If any of the players on this list are seated at the table, then FTTO will not open that table.
Put your own name in there, and FTTO will avoid opening tables that you are playing at. If there are a few sharks you don't want to play with, add them
to this list.

Version 1.04 2/5/08
1. Fixed problem where the detached chat box would be minimized instead of the table. 

Version 1.03 2/3/08
My Notes:
1. Added the ability to force the code to use a fingerprint based on the processor information, instead of the hard drive serial number.
Get last 3 HEX digits of the Software Order code (call it LTD).  CodeType (in decimal) = 0xfff - 0xLTD      convert to decimal, and put in the CodeType
box on the misc tab. The software will then use the processor type to generate the fingerprint.
example.    LTD = 87d      CodeType = 0xfff - 0x87d = 0x782    convert to decimal = 1922

Version 1.02 1/24/08
1. Added menu item under help to check our web page to see if a new version is available.
2. Changed Title Bar to "FT Table Opener"
3. New Feature: Added "Max Number of Players in Wait List" to the criteria for opening tables on the Ring Table Tab, so
that you can keep from opening tables that have a large wait list.
4. New Feature: Added ability to block a table from being opened for a specified amount of time (like 60 minutes) so that
if there are a bunch of sharks at that table you can manually block that table from being opened (for awhile) while you look for better tables.
5. New Feature: Added "Enable Group" checkboxes above each group, so you can easily select which type of tables you want to open.
6. New Feature: Added checkbox "Allow extra tables to be opened in groups". With this checked then higher priority groups will open
additional tables until the "Max Number of Tables to Open" is reached.
7. New Feature: Added checkbox to "Close lower priority tables if more higher priority tables beccome available". This means you will
always get more of your higher priority tables opened when they become available.
8. New Feature: Added checkbox "Close higher priority tables if more lower become available". This allows you to at least try to get
the quota of lower priority tables opened, even if there are a lot of higher priority table available.
NOTE: With this new ability to open more tables then you list in the Quota box, there should not be a need to specify two groups
to open the same type of tables (like you may have done in the past).
9. Fixed problem where some of the settings on the Misc tab were not being saved to the settings file (when the program was closed).
10. Removed the checkbox "Close tables that are also open in another user area". This setting is now set to "checked" in the software. 

Version 1.01  1/2/08
1. Fixed problem where some users were getting error message about not finding serial number.

Version 1.00  1/1/2008

1. Added Registration tab
2. New Feature: Added 2 additional criteria for tables: Minimum number of players per flop AND Minimum number of hands per hour.
3. New Feature: You can now copy observed files that Full Tilt creates to another folder, so that if the tables closes
you do not lose the hand history files for that table. These files can then be imported into Poker Tracker or other programs.
Additional option allows you to change the suffix of .tmp to .txt for easier import into PT. 
4. Fixed the minimize and Close buttons at top left, so they performed correctly.
5. Status is now updated continually, whether the timer is running or not.
6. Many cosmetic changes.

Version 0.39
   1. Fixed problem where the option "Close tables that are also open in another user area" was not working.
   2. Added an additional check to see if a table is open in another user area (when opening tables)
   3. When opening tables, the ftto.tablelist is now updated after every table is opened, rather than after
         the software is done opening all tables. This helps prevent other user areas from opening the same tables.

Version 0.38
   1. Add 5 as another option for the Min # of players

Version 0.37 4/12/07
   1. Fixed problem where the same table would open in multiple user areas

Version 0.36 4/2/07
   1. Made changes to allow FTTO to work with the new Full Tilt Resizeable table software
   2. Added buttons to minimize all tables and to restore all tables

Version 0.35 2/10/06
    1. This program can now be minimized to the system tray and operate without being maximized
    2. added icon for the program
    3. added windows installer for setup

Version 0.34 1/28/07
    1. added #SingleInstance Force
    2. Changed the name of some buttons to match the change that Full Tilt made to their software

Version 0.33 - 1-2-07
    1. Focus is returned to the last active application after closing tables

Version 0.32 - 1-2-07
    1. Clicking the Red X in upper right hand corner will completely close the script.
    2. Script will now not close any tables that you are seated at.
    3. Added option to "not close any tables that are visible (not minimized)"
    4. Focus will be returned to the last active application after opening tables.

Version 0.31 - 12-17-06
    1. Changed description on option to "Close empty tables and tables not in current FT Lobby".
          No functionality change in the code.

Version 0.30 - 12-8-06
    1. Changed code so only the tables that are opened will be minimized, not all open tables.
    2. Changed code so that Groups with 0 for "# Tables" would not influence what tables are closed.
    3. Changed code so that Groups with 0 for "# Tables" will not show any tables as being open.

Version 0.29 - 12/7/06
    1. Fixed bug in "open tables" that prevented it from working on games other than Hold'em

Version 0.28 - 12/5/06
    1. Significantly improved the "open tables" time due to some code inspiration from _dave_.

Version 0.27 - 11/22/06
    1. Changed the "Table Stakes" dropdown box to be "Big Blind" as an Edit text box, so that everytime
       FT adds a new stakes level the software does not have to be changed to add it. This required changes
       to the Open and Close table functions since we are now only looking at the big blind text string.

Version 0.26 - 11/13/06
    1. Fixed typo on stakes $5/$10 and $4/$8
    2. Removed the option to minimize the Lobby after opening tables
          There seems to be a bug where it is not possible to UN-minimize the lobby
          after a while. (MinimizeLobbyFlag is set to 0 in the code, and the GUI is hidden for now.)

Version 0.25 - 11/12/06
    1. Added new table stakes that Full Tilt added
    2. Fixed rare lockup problem, where if ftto.semaphore already exists,
          then this script will get locked out forever waiting for it
          to "not exist" before continuing on.

Version 0.24 - 11/8/06
    1. Cosmetic changes to GUI

Version 0.23 - 11/06/06
    1. Added some code and a semi-hidden checkbox to prevent the user from
          accidentally changing any of the GUI controls on FTTO.

Version 0.22 - 11/05/06
    1. fixed bug where some preferences were not saved correctly
    2. fixed problem where the window size would not be restored correctly
          if the program was closed while minimized

Version 0.21 - 10/30/06
    1. Changed the number of groups to 8
    2. Allowed the window to be resized, so you don't have to see all the groups
          if you don't need them.
    3. Added another criteria: Minimum Average Pot Size

Version 0.20 - 10/25/06  Major update
    1. Added ability to open different limits, up to 3, called groups
    2. Changed all the files names that this script uses to start with the prefix: ftto.
          This makes it easy to see the files associated with
          this script (if you used a previous version of this script,
          you can manually delete any old files, that don't start with "ftto")

Version 0.13 - 10/24/06
    1. Fixed an annoyance where you would have to restart FTTO if the Full Tilt
          Lobby was closed and re-opened.
          Now check for lobby ID at beginning of OpenTables and CloseTables

Version 0.12 - 10/23/06
    1. Fixed problem where if the program was closed when it was minimized,
          it would not show up on the screen the next time it was opened.
          Changed how the preferences were saved for GuiX and GuiY
          if x < 0.

Version 0.11 - 10/23/06
    1. Fixed problem where the Shift key would not be seen in other applications
          while the OpenTable subroutine was running
          (e.g. if the user was typing into notepad at the same time).
          Put {Blind} into ControlSend commands.
          Added SetKeyDelay, -1

Version 0.10 - Original Release 10/22/06

*/

; -------------------------------------------------------------------------------------------------------

; include file for keygen
;#include keygen.ahk
;#include COM.ahk
   
; This code is run when the script first starts
StartUp:


   ; AHK Initialization
   ; only allow one instance of this script to run
;   #SingleInstance force

   ; allow more than one instance
   #SingleInstance Off
   
   ; keeps the timers running
   #Persistent
   
   ; allow window title matches to be partial matches
   SetTitleMatchMode, 2
   
   ; set key sending delay to minimum, so that keystrokes are not missed in other applications
   ; improve keystrokes to dialog boxes
   ;      1st parameter is delay between Send and ControlSend commands; press duration is 2nd parameter
   ;SetKeyDelay,20,20
   
   ; have the scripts working directory be the directory that the script is in
   SetWorkingDir %a_scriptDir%  


   ; there does not seem to be a need for this, removed in ver 3.16
   ; If this OnExit line is present, then the exit subroutine gets called twice. Once
   ; when the user clicks on the Red x, and then again at the end of the subroutine with the ExitApp code.
   ; Lets add a OnExit event trap. Allows us to save preferences on exit
;   OnExit, ExitSub


   ; GLOBAL VARIABLES -
   ;     I like to minimize the number of global variables
   ;        and to declare local variables inside of functions. AHK requires you
   ;        to use subroutines in many cases, which do not allow for local vars,
   ;        so I often will make subroutines that immediately call a function
   ;        (and both the subroutine and the function can have the same name/label).
   ;
   ;     All global variables are listed and/or initialized near the top of this file.
   ;
   ;     In functions put "global" at the top of the function to allow the
   ;        function to see the global variables.
   ;        Define local and static variables used in the function
   ;        at the top of the function. E.G.
   ;              MyFunction () {
   ;                 global
   ;                 local vMyVar
   ;                 static sMyStaticVar
   ;              }

   
   Ver := "1.15"                 ; this software's version number

                    
   Title := "FT Table Opener"   ; goes in title bar for this program
   DocumentationWebAddress := "http://code.google.com/p/fttableopener/wiki/Introduction"          

   
   
   
   
   

   InitialGuiX := 20                  ; default GUI x position
   InitialGuiY := 20                  ; default GUI y position
   InitialGuiW := 700                  ; default GUI width
   InitialGuiH := 625                  ; default GUI height

   NumGroups := 8                ; number of groups of limits, labeled A, B, C on GUI

   MaxNumTables := 18            ; maximum number of tables allowed by this software to open


   
   WinCloseTime := 5             ; allow time for a window to close (in seconds)

   WinOpenTime := 10             ; allow time for a window to open (in seconds)

   TimerEnabledFlag := 0         ; flag to tell when the timer is running

   NumTablesOpen := 0            ; total number of tables open
   NumTablesOpenInGroups := 0    ; total number of tables open in all groups

   loop, %NumGroups%
      NumTablesOpen%A_Index% := 0    ; init the number of open tables in each group
      
   DisplayTimerPeriod := 5000       ; display the status every 2 seconds
   DisplayTimerPriority := -100     ; set the timer priority low
   
   BlockTableNameList := ""            ; list of tables that are blocked from opening again for BlockTableMinutes
   BlockTableTimeList := ""            ; time that the table was blocked
   


   



   
    



   ; The following global variables are initialized in the code following this list.
   ; They are listed here for clarity and easy reference.

   ; Temp

   ; GuiX                        ; the x position of the GUI
   ; GuiY                        ; the y position of the GUI
   ; GuiW                        ;  gui width

   ; DesiredGames                 ; the game choice (Hold'em, etc.)

   ; DesiredTablesOpen%X%        ; the desired # of tables to open for group X
   ; DesiredNumSeats%X%          ; desired number of seats at tables for group X
   ; DesiredMinNumPlayers%X%     ; desired minumum number of players for group X
   ; DesiredMaxNumPlayers%X%     ; desired maximum number of players for group X
   ; DesiredBigBlind%X%            ; desired table stakes for group X ($1/$2, etc.)
   ; DesiredType%X%              ; desired game type for groupX   (NL, Limit, etc.)
   ; DesiredMinPot%X%            ; desired minimum average pot size


   ; CloseTablesWithFewFlag      ; flag, if set, close tables with too few players (less than DesiredMinNumPlayers%X%)
   ; CloseTablesWithManyFlag      ; flag, if set, close tables with too many players (more than DesiredMaxNumPlayers%X%)
   ; CloseTablesNotInLobbyFlag   ; flag, if set, close tables not in current lobby
   ; CloseTablesNotInEnabledGroupFlag   ; flag, if set, close tables not in any group
   ; CloseTablesInOtherUserAreaFlag   ; flag, if set, close tables also open in other user areas
   ; MinimizeTablesFlag          ; flag, if set, minimize tables after opening them
   ; MinimizeLobbyFlag           ; flag, if set, minimize lobby after opening or closing tables


   ; TimerPeriodMin              ; Timer period in Minutes

   ; GroupTableName              ; defines the window name for tables
   ; GroupLobbyName              ; defines the window name for the lobby

   ; These groups define how we detect the Full Tilt tables and lobby
   ;        modify these if there is confusion with other open windows
   ; FTPTables group:   contains the word "Logged In As", but does not contain "Full Tilt Poker"
   GroupAdd, GroupTableName, Logged In As ahk_class FTC_TableViewFull,,, Full Tilt Poker
   ; FTPLobby group:  contains "Full Tilt Poker - Logged", no text exclusions
   GroupAdd, GroupLobbyName, Full Tilt Poker - Logged ahk_class FTC_Lobby,,,



   ; create the directory for the settings
   FileCreateDir, Settings

   ; read in our preferences from the .ini file
   IniRead, GuiX, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, GuiX, %InitialGuiX%
   IniRead, GuiY, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, GuiY, %InitialGuiY%
   
   IniRead, OrderCode, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, OrderCode, Place_Order_Code_Here
   IniRead, OrderUnlockCode, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, OrderUnlockCode, Place_Unlock_Code_Here
  
  
   IniRead , MaxNumTablesInGroups, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, MaxNumTablesInGroups, 12
   IniRead , DesiredGames, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredGames, 1-HOLD'EM

;outputdebug, reading MaxNumTablesInGroups= %MaxNumTablesInGroups%

   Loop, %NumGroups%
   {
      IniRead , EnabledGroup%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, EnabledGroup%A_index%, 0
      IniRead , DesiredTablesOpen%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredTablesOpen%A_index%, 0
      IniRead , DesiredNumSeats%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredNumSeats%A_index%, 6
      IniRead , DesiredMinNumPlayers%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinNumPlayers%A_index%, 4
      IniRead , DesiredMaxNumPlayers%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMaxNumPlayers%A_index%, 8
      IniRead , DesiredBigBlind%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredBigBlind%A_index%, 1
      IniRead , DesiredType%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredType%A_index%, NL
      IniRead , DesiredOptions%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredOptions%A_index%, None
      IniRead , DesiredMaxWaitNum%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMaxWaitNum%A_index%, 50
      IniRead , DesiredMinPot%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinPot%A_index%, 0
      IniRead , DesiredMinPlyrPerFlop%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinPlyrPerFlop%A_index%, 0
      IniRead , DesiredMinHandsPerHour%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinHandsPerHour%A_index%, 0
      IniRead , DesiredMaxNumShortStacks%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMaxNumShortStacks%A_index%, 50      
   }



   IniRead , AllowExtraOpeningsFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, AllowExtraOpeningsFlag, 1
   IniRead , CloseLowerPriorityTablesFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseLowerPriorityTablesFlag, 1
   IniRead , CloseHigherPriorityTablesFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseHigherPriorityTablesFlag, 1      

   IniRead , CloseTablesWithFewFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesWithFewFlag, 1
   IniRead , CloseTablesWithManyFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesWithManyFlag, 1
   IniRead , CloseTablesNotMeetingCriteriaFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesNotMeetingCriteriaFlag, 1   
   IniRead , CloseTablesNotInLobbyFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesNotInLobbyFlag, 1
   IniRead , CloseTablesNotInEnabledGroupFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesNotInEnabledGroupFlag, 0
;   IniRead , CloseTablesInOtherUserAreaFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesInOtherUserAreaFlag, 0
   IniRead , DoNotCloseTablesThatAreMaximizedFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DoNotCloseTablesThatAreMaximizedFlag, 1

   IniRead , MinimizeTablesFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, MinimizeTablesFlag ,1
   IniRead , MinimizeLobbyFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, MinimizeLobbyFlag ,0
   IniRead , TimerPeriodMin, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, TimerPeriodMin, 5
   

   ; Misc
   IniRead , CodeType, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CodeType ,1   
   IniRead , CopyObservedFilesFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CopyObservedFilesFlag ,0   
   IniRead , SourceFolder, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, SourceFolder ,c:\Program Files\Full Tilt Poker\HandHistory
   IniRead , DestinationFolder, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DestinationFolder, %A_MyDocuments%
   IniRead , ChangeObservedFilesSuffixFlag, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, ChangeObservedFilesSuffixFlag ,0
   IniRead , BlockTableControl, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, BlockTableControl,Alt & F1
   IniRead , BlockTableMinutes, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, BlockTableMinutes ,60 

   IniRead , ShortStackSizeBB, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, ShortStackSizeBB ,25
   IniRead , SharkListEnabled, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, SharkListEnabled, 0
   IniRead , SharkList, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, SharkList ,Put_your_name_and_others_here
   
  
   
   ; we don't allow the user to change this flag any longer
   CloseTablesInOtherUserAreaFlag := 1

   ; ****************   there seems to be a bug where (after a while) is not possible to UN-minimize the FT lobby,      *******************
   ; ****************      so I'm disabling that feature until it is understood.                                        *******************
   ; ****************      set this parameter to 0 so the lobby will not be minimized.
   ;MinimizeLobbyFlag := 0



   ; The main GUI will have a Gui number of 99
   Gui, 99:Default


   ; use this icon if it exists
   IfExist, ftto.ico
      Menu, Tray, Icon, ftto.ico



   ; System Tray items
   if A_IsCompiled
      Menu, Tray, NoStandard                          ; don't put standard tray options in the compiled version

   Menu, Tray, add
   Menu, Tray, add, Minimize To Tray, MinimizeToTray
   Menu, Tray, add, Restore
   Menu, Tray, add
   Menu, Tray, add, Close FTTO, Close

   Menu, Tray, Default, Restore                       ; make this the option when the user double clicks the tray icon
   Menu, Tray, Click, 2                               ; require a double click to do a restore


   ; Define the GUI interface

   ; Define the Menu Bar
   ; Create the sub-menus for the menu bar:
   Menu, FileMenu, Add, E&xit, ExitSub
   ;Menu, FileMenu, Add     
   Menu, HelpMenu, Add, &Documentation, Documentation
   Menu, HelpMenu, Add, &About, About
   ; Create the menu bar by attaching the sub-menus to it:
   Menu, MyMenuBar, Add, &File, :FileMenu
   Menu, MyMenuBar, Add, &Help, :HelpMenu
   ; Attach the menu bar to the window:

   ; Attach the menu bar to the window:
   Gui, Menu, MyMenuBar


Gui, Add, Tab, x0 y0 w1000 h785 , Ring Tables|Miscellaneous


Gui, Tab, Ring Tables

Gui, Add, CheckBox, x1200 y7 w120 h20 vKeepFocusHere, Focus Kept here
Gui, Font, bold, 
Gui, Font, norm, 
Gui, Add, Text, x26 y37 w200 h30 vStatus1, Status1:
Gui, Add, Button, x236 y30 w210 h20 gOpenTables vOpenTablesButton, Open Tables using Criteria below
Gui, Add, Text, x216 y53 w250 h20 +Center cBlue, Opening Table Criteria (Priority A>B>...>H)
Gui, Add, Text, x20 y77 w86 h30 +Right, Max Number Tables to Open
Gui, Add, DropDownList, x116 y80 w90 h21 vMaxNumTablesInGroups gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, Text, x230 y83 w86 h20 +Right, FT Lobby
Gui, Add, DropDownList, x326 y80 w90 h21 vDesiredGames gUpdateVariables R6, 1-HOLD'EM|2-OMAHA H/L|3-OMAHA|4-STUD H/L|5-STUD|6-RAZZ
Gui, Add, Button, x530 y40 w110 h20 gRestoreTables vRestoreTablesButton, Un-Minimize Tables
Gui, Add, Button, x530 y70 w110 h20 gMinimizeTables vMinimizeTablesButton, Minimize Tables
Gui, Add, Text, x20 y110 w86 h20 +Right, Enable Group
Gui, Add, Text, x20 y125 w86 h30 +Right, # Tables to Open (Quota)
Gui, Add, Text, x20 y155 w86 h20 +Right, # Seats
Gui, Add, Text, x20 y180 w86 h20 +Right, Min. # Players
Gui, Add, Text, x20 y205 w86 h20 +Right, Max. # Players
Gui, Add, Text, x20 y230 w86 h20 +Right, Big Blind (Big Bet)
Gui, Add, Text, x20 y255 w86 h20 +Right, Table Type
Gui, Add, Text, x20 y280 w86 h20 +Right, Table Options
Gui, Add, Text, x20 y305 w86 h20 +Right, Max. Wait Num.
Gui, Add, Text, x20 y330 w86 h20 +Right, Min. Avg. Pot
Gui, Add, Text, x20 y355 w86 h20 +Right, Min. `% Plyrs/Flop
Gui, Add, Text, x20 y380 w86 h20 +Right, Min. Hands/Hr
Gui, Add, Text, x2 y405 w104 h20 +Right, Max. # Short Stacks
Gui, Add, CheckBox, x136 y107 w50 h20 vEnabledGroup1 gUpdateVariables, A
Gui, Add, CheckBox, x206 y107 w50 h20 vEnabledGroup2 gUpdateVariables, B
Gui, Add, CheckBox, x276 y107 w50 h20 vEnabledGroup3 gUpdateVariables, C
Gui, Add, CheckBox, x346 y107 w50 h20 vEnabledGroup4 gUpdateVariables, D
Gui, Add, CheckBox, x416 y107 w50 h20 vEnabledGroup5 gUpdateVariables, E
Gui, Add, CheckBox, x486 y107 w50 h20 vEnabledGroup6 gUpdateVariables, F
Gui, Add, CheckBox, x556 y107 w50 h20 vEnabledGroup7 gUpdateVariables, G
Gui, Add, CheckBox, x626 y107 w50 h20 vEnabledGroup8 gUpdateVariables, H
Gui, Add, DropDownList, x116 y127 w60 h20 vDesiredTablesOpen1 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x186 y127 w60 h20 vDesiredTablesOpen2 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x256 y127 w60 h20 vDesiredTablesOpen3 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x326 y127 w60 h20 vDesiredTablesOpen4 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x396 y127 w60 h20 vDesiredTablesOpen5 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x466 y127 w60 h20 vDesiredTablesOpen6 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x536 y127 w60 h20 vDesiredTablesOpen7 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x606 y127 w60 h20 vDesiredTablesOpen8 gUpdateVariables R19, 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
Gui, Add, DropDownList, x116 y152 w60 h20 vDesiredNumSeats1 gUpdateVariables R6, 1|2|5|6||8|9
Gui, Add, DropDownList, x186 y152 w60 h20 vDesiredNumSeats2 gUpdateVariables R6, 1|2|5|6||8|9
Gui, Add, DropDownList, x256 y152 w60 h20 vDesiredNumSeats3 gUpdateVariables R6, 1|2|5|6||8|9
Gui, Add, DropDownList, x326 y152 w60 h20 vDesiredNumSeats4 gUpdateVariables R6, 1|2|5|6||8|9
Gui, Add, DropDownList, x396 y152 w60 h20 vDesiredNumSeats5 gUpdateVariables R6, 1|2|5|6||8|9
Gui, Add, DropDownList, x466 y152 w60 h10 vDesiredNumSeats6 gUpdateVariables R6, 1|2|5|6||8|9
Gui, Add, DropDownList, x536 y152 w60 h20 vDesiredNumSeats7 gUpdateVariables R6, 1|2|5|6||8|9
Gui, Add, DropDownList, x606 y152 w60 h20 vDesiredNumSeats8 gUpdateVariables R6, 1|2|5|6||8|9


Gui, Add, DropDownList, x116 y177 w60 h21 vDesiredMinNumPlayers1 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x186 y177 w60 h21 vDesiredMinNumPlayers2 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x256 y177 w60 h21 vDesiredMinNumPlayers3 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x326 y177 w60 h21 vDesiredMinNumPlayers4 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x396 y177 w60 h21 vDesiredMinNumPlayers5 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x466 y177 w60 h21 vDesiredMinNumPlayers6 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x536 y177 w60 h21 vDesiredMinNumPlayers7 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x606 y177 w60 h21 vDesiredMinNumPlayers8 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9

Gui, Add, DropDownList, x116 y202 w60 h21 vDesiredMaxNumPlayers1 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x186 y202 w60 h21 vDesiredMaxNumPlayers2 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x256 y202 w60 h21 vDesiredMaxNumPlayers3 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x326 y202 w60 h21 vDesiredMaxNumPlayers4 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x396 y202 w60 h21 vDesiredMaxNumPlayers5 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x466 y202 w60 h21 vDesiredMaxNumPlayers6 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x536 y202 w60 h21 vDesiredMaxNumPlayers7 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9
Gui, Add, DropDownList, x606 y202 w60 h21 vDesiredMaxNumPlayers8 gUpdateVariables R10, 0|1|2|3|4||5|6|7|8|9


Gui, Add, Edit, x116 y227 w60 h20 vDesiredBigBlind1 gUpdateVariables, %DesiredBigBlind1%
Gui, Add, Edit, x186 y227 w60 h20 vDesiredBigBlind2 gUpdateVariables, %DesiredBigBlind2%
Gui, Add, Edit, x256 y227 w60 h20 vDesiredBigBlind3 gUpdateVariables, %DesiredBigBlind3%
Gui, Add, Edit, x326 y227 w60 h20 vDesiredBigBlind4 gUpdateVariables, %DesiredBigBlind4%
Gui, Add, Edit, x396 y227 w60 h20 vDesiredBigBlind5 gUpdateVariables, %DesiredBigBlind5%
Gui, Add, Edit, x466 y227 w60 h20 vDesiredBigBlind6 gUpdateVariables, %DesiredBigBlind6%
Gui, Add, Edit, x536 y227 w60 h20 vDesiredBigBlind7 gUpdateVariables, %DesiredBigBlind7%
Gui, Add, Edit, x606 y227 w60 h20 vDesiredBigBlind8 gUpdateVariables, %DesiredBigBlind8%
Gui, Add, DropDownList, x116 y252 w60 h21 vDesiredType1 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x186 y252 w60 h21 vDesiredType2 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x256 y252 w60 h21 vDesiredType3 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x326 y252 w60 h21 vDesiredType4 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x396 y252 w60 h21 vDesiredType5 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x466 y252 w60 h21 vDesiredType6 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x536 y252 w60 h21 vDesiredType7 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x606 y252 w60 h21 vDesiredType8 gUpdateVariables R3, NL|PL|FL
Gui, Add, DropDownList, x116 y277 w60 h21 vDesiredOptions1 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, DropDownList, x186 y277 w60 h21 vDesiredOptions2 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, DropDownList, x256 y277 w60 h21 vDesiredOptions3 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, DropDownList, x326 y277 w60 h21 vDesiredOptions4 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, DropDownList, x396 y277 w60 h21 vDesiredOptions5 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, DropDownList, x466 y277 w60 h21 vDesiredOptions6 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, DropDownList, x536 y277 w60 h21 vDesiredOptions7 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, DropDownList, x606 y277 w60 h21 vDesiredOptions8 gUpdateVariables R6, None|D|AD|C|E|S
Gui, Add, Edit, x116 y302 w60 h20 vDesiredMaxWaitNum1 gUpdateVariables number, %DesiredMaxWaitNum1%
Gui, Add, Edit, x186 y302 w60 h20 vDesiredMaxWaitNum2 gUpdateVariables number, %DesiredMaxWaitNum2%
Gui, Add, Edit, x256 y302 w60 h20 vDesiredMaxWaitNum3 gUpdateVariables number, %DesiredMaxWaitNum3%
Gui, Add, Edit, x326 y302 w60 h20 vDesiredMaxWaitNum4 gUpdateVariables number, %DesiredMaxWaitNum4%
Gui, Add, Edit, x396 y302 w60 h20 vDesiredMaxWaitNum5 gUpdateVariables number, %DesiredMaxWaitNum5%
Gui, Add, Edit, x466 y302 w60 h20 vDesiredMaxWaitNum6 gUpdateVariables number, %DesiredMaxWaitNum6%
Gui, Add, Edit, x536 y302 w60 h20 vDesiredMaxWaitNum7 gUpdateVariables number, %DesiredMaxWaitNum7%
Gui, Add, Edit, x606 y302 w60 h20 vDesiredMaxWaitNum8 gUpdateVariables number, %DesiredMaxWaitNum8%
Gui, Add, Edit, x116 y327 w60 h20 vDesiredMinPot1 gUpdateVariables, %DesiredMinPot1%
Gui, Add, Edit, x186 y327 w60 h20 vDesiredMinPot2 gUpdateVariables, %DesiredMinPot2%
Gui, Add, Edit, x256 y327 w60 h20 vDesiredMinPot3 gUpdateVariables, %DesiredMinPot3%
Gui, Add, Edit, x326 y327 w60 h20 vDesiredMinPot4 gUpdateVariables, %DesiredMinPot4%
Gui, Add, Edit, x396 y327 w60 h20 vDesiredMinPot5 gUpdateVariables, %DesiredMinPot5%
Gui, Add, Edit, x466 y327 w60 h20 vDesiredMinPot6 gUpdateVariables, %DesiredMinPot6%
Gui, Add, Edit, x536 y327 w60 h20 vDesiredMinPot7 gUpdateVariables, %DesiredMinPot7%
Gui, Add, Edit, x606 y327 w60 h20 vDesiredMinPot8 gUpdateVariables, %DesiredMinPot8%
Gui, Add, Edit, x116 y352 w60 h20 vDesiredMinPlyrPerFlop1 gUpdateVariables number, %DesiredMinPlyrPerFlop1%
Gui, Add, Edit, x186 y352 w60 h20 vDesiredMinPlyrPerFlop2 gUpdateVariables number, %DesiredMinPlyrPerFlop2%
Gui, Add, Edit, x256 y352 w60 h20 vDesiredMinPlyrPerFlop3 gUpdateVariables number, %DesiredMinPlyrPerFlop3%
Gui, Add, Edit, x326 y352 w60 h20 vDesiredMinPlyrPerFlop4 gUpdateVariables number, %DesiredMinPlyrPerFlop4%
Gui, Add, Edit, x396 y352 w60 h20 vDesiredMinPlyrPerFlop5 gUpdateVariables number, %DesiredMinPlyrPerFlop5%
Gui, Add, Edit, x466 y352 w60 h20 vDesiredMinPlyrPerFlop6 gUpdateVariables number, %DesiredMinPlyrPerFlop6%
Gui, Add, Edit, x536 y352 w60 h20 vDesiredMinPlyrPerFlop7 gUpdateVariables number, %DesiredMinPlyrPerFlop7%
Gui, Add, Edit, x606 y352 w60 h20 vDesiredMinPlyrPerFlop8 gUpdateVariables number, %DesiredMinPlyrPerFlop8%
Gui, Add, Edit, x116 y377 w60 h20 vDesiredMinHandsPerHour1 gUpdateVariables number, %DesiredMinHandsPerHour1%
Gui, Add, Edit, x186 y377 w60 h20 vDesiredMinHandsPerHour2 gUpdateVariables number, %DesiredMinHandsPerHour2%
Gui, Add, Edit, x256 y377 w60 h20 vDesiredMinHandsPerHour3 gUpdateVariables number, %DesiredMinHandsPerHour3%
Gui, Add, Edit, x326 y377 w60 h20 vDesiredMinHandsPerHour4 gUpdateVariables number, %DesiredMinHandsPerHour4%
Gui, Add, Edit, x396 y377 w60 h20 vDesiredMinHandsPerHour5 gUpdateVariables number, %DesiredMinHandsPerHour5%
Gui, Add, Edit, x466 y377 w60 h20 vDesiredMinHandsPerHour6 gUpdateVariables number, %DesiredMinHandsPerHour6%
Gui, Add, Edit, x536 y377 w60 h20 vDesiredMinHandsPerHour7 gUpdateVariables number, %DesiredMinHandsPerHour7%
Gui, Add, Edit, x606 y377 w60 h20 vDesiredMinHandsPerHour8 gUpdateVariables number, %DesiredMinHandsPerHour8%
Gui, Add, Edit, x116 y402 w60 h20 vDesiredMaxNumShortStacks1 gUpdateVariables number, %DesiredMaxNumShortStacks1%
Gui, Add, Edit, x186 y402 w60 h20 vDesiredMaxNumShortStacks2 gUpdateVariables number, %DesiredMaxNumShortStacks2%
Gui, Add, Edit, x256 y402 w60 h20 vDesiredMaxNumShortStacks3 gUpdateVariables number, %DesiredMaxNumShortStacks3%
Gui, Add, Edit, x326 y402 w60 h20 vDesiredMaxNumShortStacks4 gUpdateVariables number, %DesiredMaxNumShortStacks4%
Gui, Add, Edit, x396 y402 w60 h20 vDesiredMaxNumShortStacks5 gUpdateVariables number, %DesiredMaxNumShortStacks5%
Gui, Add, Edit, x466 y402 w60 h20 vDesiredMaxNumShortStacks6 gUpdateVariables number, %DesiredMaxNumShortStacks6%
Gui, Add, Edit, x536 y402 w60 h20 vDesiredMaxNumShortStacks7 gUpdateVariables number, %DesiredMaxNumShortStacks7%
Gui, Add, Edit, x606 y402 w60 h20 vDesiredMaxNumShortStacks8 gUpdateVariables number, %DesiredMaxNumShortStacks8%
Gui, Add, CheckBox, x16 y420 w300 h20 vAllowExtraOpeningsFlag Checked gUpdateVariables, Allow extra tables to be opened in groups (above Quota)
Gui, Add, CheckBox, x16 y440 w300 h30 vCloseLowerPriorityTablesFlag Checked gUpdateVariables, Close lower priority tables (that are over quota) if more higher priority tables become available
Gui, Add, CheckBox, x16 y470 w300 h30 vCloseHigherPriorityTablesFlag Checked gUpdateVariables, Close higher priority tables (that are over quota) if more lower become available (to help reach their quota)
Gui, Add, CheckBox, x336 y470 w320 h20 vCloseTablesNotInLobbyFlag gUpdateVariables, Close empty tables and tables not in current FT lobby
Gui, Add, CheckBox, x336 y490 w360 h20 vCloseTablesNotInEnabledGroupFlag gUpdateVariables, Close tables in FT lobby but not part of any Enabled group above
Gui, Add, CheckBox, x336 y510 w320 h20 vDoNotCloseTablesThatAreMaximizedFlag gUpdateVariables, Do not close tables that are visible (i.e. not minimized)
Gui, Add, CheckBox, x336 y530 w320 h20 vCloseTablesWithFewFlag Checked gUpdateVariables, Close tables not meeting "Min # Players" criteria
Gui, Add, CheckBox, x336 y550 w320 h20 vCloseTablesWithManyFlag Checked gUpdateVariables, Close tables not meeting "Max # Players" criteria
Gui, Add, CheckBox, x336 y570 w320 h30 vCloseTablesNotMeetingCriteriaFlag Checked gUpdateVariables, Close tables not meeting (almost all) main criteria`n    (Wait Num and Short Stacks and not considered)
Gui, Add, Text, x386 y455 w130 h20 cBlue, Closing Table Criteria:
Gui, Add, Button, x336 y427 w180 h20 gCloseTables vCloseTablesButton, Close Tables using Criteria below
Gui, Add, Button, x536 y427 w120 h20 gCloseAllTables vCloseAllButton, Close All Tables
Gui, Add, Text, x56 y510 w250 h20 cBlue, Automatic Opening and Closing
Gui, Add, Text, x140 y533 w140 h20 , Timer Period (in minutes)
Gui, Add, DropDownList, x26 y530 w100 h21 vTimerPeriodMin gUpdateVariables R15, .25|.5|.75|1|1.5|2|3|5|7|10|15|20|30|40|60
Gui, Add, Button, x26 y560 w100 h20 gStartTimer vStartTimerButton Default, Start
Gui, Add, Button, x26 y560 w100 h20 gStopTimer vStopTimerButton, STOP
Gui, Add, Text, x140 y563 w160 h20 vStatus, Status:


;Gui, Tab, SnG Tables 
   
;Gui, Font, bold, 
;Gui, Add, Text, x16 y37 w160 h20 +center, SnG Tables (coming soon)
;Gui, Font, norm 
   
   
   
   
Gui, Tab, Miscellaneous
Gui, Font, bold, 
Gui, Add, Text, x20 y40 w200 h20 +center, Miscellaneous
Gui, Font, norm, 

   Gui, Add, Text, x20 y63 w80 h30 , Code Type`n(leave at "1")   
   Gui, Add, Edit, x110 y65 w40 h20 vCodeType gUpdateVariables , %CodeType% 

Gui, Add, CheckBox, x20 y97 w170 h20 vMinimizeTablesFlag Checked gUpdateVariables, Minimize Tables after Opening
Gui, Add, CheckBox, x20 y117 w240 h20 vMinimizeLobbyFlag gUpdateVariables, Minimize Lobby after Opening/Closing Tables

Gui, Font, bold, 
Gui, Add, Text, x20 y150 w400 h20 , Copying Observed Hand History Files to another Folder
Gui, Font, norm, 
Gui, Add, CheckBox, x50 y170 w380 h20 vCopyObservedFilesFlag  gUpdateVariables, Copy Observed hand files (*.tmp) to destination folder when timer is running
Gui, Add, Button, x446 y167 w100 h20 gCopyObservedFiles vCopyObservedFilesButton center, Copy Now
Gui, Add, CheckBox, x50 y200 w380 h20 vChangeObservedFilesSuffixFlag gUpdateVariables, When copying, change the suffix of the observed hand files to .txt
Gui, Add, Button, x50 y230 w170 h20 gSelectSourceFolder vSelectSourceFolderButton center, Select Observed Hands Folder
Gui, Add, Button, x50 y260 w170 h20 gSelectDestinationFolder vSelectDestinationFolderButton center, Select Destination Folder
Gui, Add, Edit, x230 y230 w300 h20 vSourceFolder gUpdateVariables ReadOnly, %SourceFolder%
Gui, Add, Edit, x230 y260 w300 h20 vDestinationFolder gUpdateVariables ReadOnly, %DestinationFolder%
Gui, Font, bold, 
Gui, Add, Text, x20 y290 w400 h20 , Blocking a Table from Opening Again
Gui, Font, norm, 
Gui, Add, Edit, x40 y310 w50 h20 vBlockTableControl gUpdateVariables, %BlockTableControl%
Gui, Add, Text, x100 y315 w395 h20, This key closes active table and blocks it from opening again for this many minutes: 
Gui, Add, Edit, x500 y310 w50 h20 vBlockTableMinutes gUpdateVariables number, %BlockTableMinutes%
Gui, Font, bold, 
Gui, Add, Text, x20 y340 w220 h20 , A Short Stack is this many Big Blinds: 
Gui, Font, norm, 
Gui, Add, Edit, x240 y335 w50 h20 vShortStackSizeBB gUpdateVariables number, %ShortStackSizeBB%
Gui, Font, bold, 
Gui, Add, CheckBox, x20 y360 w420 h20 vSharkListEnabled gUpdateVariables, Avoid opening tables with these players (put commas between them):
Gui, Font, norm, 
Gui, Add, Edit, x440 y360 w250 h20 vSharkList gUpdateVariables, %SharkList%


  




   ; Show the GUI...   if GuiX is less then 0, it might be off the page or minimized, so restore GUI to 0,0  
   if GuiX < 0
   Gui, Show, x%InitialGuiX% y%InitialGuiY% h%InitialGuiH% w%InitialGuiW%, %Title%
   else
   Gui, Show, x%GuiX% y%GuiY% h%InitialGuiH% w%InitialGuiW%, %Title%






   ; save the preferences from the .ini file to the GUI
   
   ; NOTE: really only the ChooseString ones are needed here...   the edit boxes are filled in in the GUI commands above.
   
   
;outputdebug, guicontrol write   MaxNumTablesInGroups= %MaxNumTablesInGroups%
   
   GuiControl, ChooseString, MaxNumTablesInGroups, %MaxNumTablesInGroups%   
   GuiControl, ChooseString, DesiredGames, %DesiredGames%
   Loop, %NumGroups%
   {
      GuiControl,, EnabledGroup%A_index%, % EnabledGroup%A_index%
      GuiControl, ChooseString, DesiredTablesOpen%A_index%, % DesiredTablesOpen%A_index%
      GuiControl, ChooseString, DesiredNumSeats%A_index%, % DesiredNumSeats%A_index%
      GuiControl, ChooseString, DesiredMinNumPlayers%A_index%, % DesiredMinNumPlayers%A_index%
      GuiControl, ChooseString, DesiredMaxNumPlayers%A_index%, % DesiredMaxNumPlayers%A_index%
      ; the Gui, Add command puts the starting value for the DesiredBigBlind in the edit box,
      ;        so the following is not needed
      ;GuiControl, ChooseString, DesiredBigBlind%A_index%, % DesiredBigBlind%A_index%
      GuiControl, ChooseString, DesiredType%A_index%, % DesiredType%A_index%
      GuiControl, ChooseString, DesiredOptions%A_index%, % DesiredOptions%A_index%      
      ; the Gui, Add command puts the starting value for the DesiredMinPot in the edit box,
      ;        so the following is not needed
      ; GuiControl, , DesiredMinPot%A_index%, % DesiredMinPot%A_index%

   }


   GuiControl,, AllowExtraOpeningsFlag, %AllowExtraOpeningsFlag%
   GuiControl,, CloseLowerPriorityTablesFlag, %CloseLowerPriorityTablesFlag%
   GuiControl,, CloseHigherPriorityTablesFlag, %CloseHigherPriorityTablesFlag%

   GuiControl,, CloseTablesWithFewFlag, %CloseTablesWithFewFlag%
   GuiControl,, CloseTablesWithManyFlag, %CloseTablesWithManyFlag%
   GuiControl,, CloseTablesNotMeetingCriteriaFlag, %CloseTablesNotMeetingCriteriaFlag%   
   GuiControl,, CloseTablesNotInLobbyFlag, %CloseTablesNotInLobbyFlag%
   GuiControl,, CloseTablesNotInEnabledGroupFlag, %CloseTablesNotInEnabledGroupFlag%
;   GuiControl,, CloseTablesInOtherUserAreaFlag, %CloseTablesInOtherUserAreaFlag%
   GuiControl,, DoNotCloseTablesThatAreMaximizedFlag, %DoNotCloseTablesThatAreMaximizedFlag%
   GuiControl,, MinimizeTablesFlag, %MinimizeTablesFlag%
   GuiControl,, MinimizeLobbyFlag, %MinimizeLobbyFlag%
   GuiControl, ChooseString, TimerPeriodMin, %TimerPeriodMin%
   
   ; Misc
   GuiControl,, CopyObservedFilesFlag, %CopyObservedFilesFlag%   
   GuiControl,, ChangeObservedFilesSuffixFlag, %ChangeObservedFilesSuffixFlag%   
   GuiControl,, SharkListEnabled, %SharkListEnabled%

  
   

   ; The Start and Stop button overlap;  hide the Stop button for now
   GuiControl, Hide, StopTimerButton


   ; update variables that are dependent on the GUI
   Gosub, UpdateVariables

   ; Lets create our lock file, for the OnExit trap to see. This tells other
   ;     instances of this program that another instance is still running.
   FileDelete, Settings\ftto.%A_UserName%.%A_ComputerName%.lock
   FileAppend, %A_UserName%.%A_ComputerName% is locked, Settings\ftto.%A_UserName%.%A_ComputerName%.lock

   ; find out how may tables are currently open in each group
   ;UpdateNumTablesOpen()
   
   ; Show the status on the GUI
   DisplayStatus("Stopped")

   ; don't allow any button to be the default button (that will work with the ENTER key)
   GuiControl, -default, StartTimerButton
   

   
   SetTimer, DisplayStatus, %DisplayTimerPeriod%, %DisplayTimerPriority%

Return

; =======================================================================================================
;              SUBROUTINES
; =======================================================================================================

/*
F10::
   WinId := WinActive("A")
   junko := HeroSeated(WinId)
   msgbox %junko%
return
*/
/*
F9::
   CloseTableInOtherGroup(1)
return

F10::
   CloseTableInOtherGroup(2)
return
*/

;debug info

/*
F10::
outputdebug, BlockTableNameList= %BlockTableNameList%
outputdebug, BlockTableTimeList= %BlockTableTimeList%
return
*/


MinimizeToTray:
   WinHide, %Title%
return

; ------------------------------------------------------------------------------

Restore:
   WinShow, %Title%
   WinActivate, %Title%
   WinRestore, %Title%
return


; ------------------------------------------------------------------------------

Close:
   WinShow, %Title%
   WinActivate, %Title%
   WinRestore, %Title%
   Goto, ExitSub
; ------------------------------------------------------------------------------

;Minimize-Button
99GuiSize:
if Errorlevel = 1   ;Is '1' when Minimize-Button was pressed
{
   WinHide, %Title%
}
return

; -------------------------------------------------------------------------------------------------------
; Display About Message box for menu item "About"
About:
   MsgBox %Title% `nVersion %Ver%  
Return

; -------------------------------------------------------------------------------------------------------

; Open this web page for menu item "Help"
Documentation:
   Run %DocumentationWebAddress%
Return

; -------------------------------------------------------------------------------------------------------


DisplayStatus:
   DisplayStatus()
Return

; -------------------------------------------------------------------------------------------------------

; Enable the Timer to start automatically opening and closing tables on a periodic basis
StartTimer:
   GuiControl, Hide, StartTimerButton
   GuiControl, Show, StopTimerButton
   TimerEnabledFlag := 1

   ; run the openandclosetables subroutine
   Gosub, OpenAndCloseTables
   ; start the timer to repeat opening/closing tables
   SetTimer, OpenAndCloseTables, % TimerPeriodMin * 60000
Return

; -------------------------------------------------------------------------------------------------------

; Disable the timer
StopTimer:

   GuiControl, Hide, StopTimerButton
   GuiControl, Show, StartTimerButton
   TimerEnabledFlag := 0
   SetTimer, OpenAndCloseTables, Off

   DisplayStatus("Stopped")

Return

; -------------------------------------------------------------------------------------------------------

; open and close tables... this sub is called by the timer
OpenAndCloseTables:

;outputdebug, In OpenAndCloseTables !!!!!!!!!!!!!!!!!!!

   ; make sure the timer is enabled before
   ; this IF was needed, else the timer would still fire one extra time, if we stop the timer while the
   ;     OpenTable subroutine was still in progress
   if TimerEnabledFlag
   {
      CloseTables()
      OpenTables()
   }
   else
   {
      SetTimer, OpenAndCloseTables, Off
      DisplayStatus("Stopped")
   }

   ; copy the observed hand histories
   if CopyObservedFilesFlag
      Gosub CopyObservedFiles


Return

; -------------------------------------------------------------------------------------------------------
; unminimize all tables
RestoreTables:
   RestoreTables()
Return

; -------------------------------------------------------------------------------------------------------
; minimize all tables
MinimizeTables:
   MinimizeTables()
Return

; -------------------------------------------------------------------------------------------------------
SelectSourceFolder:
   FileSelectFolder, SourceFolder,, 2, Select the Source Folder
   if ! ErrorLevel
   {
      Gui, 99:Default
      GuiControl,,SourceFolder, %SourceFolder%
   }     
Return
; -------------------------------------------------------------------------------------------------------
SelectDestinationFolder:
   FileSelectFolder, DestinationFolder,, 3, Select the Destination Folder
   if ! ErrorLevel
   {
      Gui, 99:Default      
      GuiControl,,DestinationFolder, %DestinationFolder%
   }    
Return
; -------------------------------------------------------------------------------------------------------
CopyObservedFiles:
   ; Copy GUI selections to variables, incase folder names were just entered
   Gui, 99:Default
   GUI, Submit, NoHide
   ; copy the observed hand histories
   ; if we are supposed to change the suffix to .txt, then do so, else don't change the suffix
   if ChangeObservedFilesSuffixFlag
      FileCopy, %SourceFolder%\*.tmp, %DestinationFolder%\*.txt,1  
   else   
      FileCopy, %SourceFolder%\*.tmp, %DestinationFolder%,1
Return

; -------------------------------------------------------------------------------------------------------

BlockTable:
   BlockTable()
return

BlockTable()
{
   global
   local vWinId
   ; get the active table name
   vWinId := WinActive("A")
   ; get the table name of this table or "" if it is a tournament
   vTableName := TableRingName(vWinId)
   ; if this table is a ring table, then add it to block list and close it
   if (vTableName)
   {
      ; add this table to the BlockTableList (if it is not on the list)
      BlockTableNameList := AddItemToList(BlockTableNameList,vTableName)
      ; add the time to the BlockTableTimeList
      BlockTableTimeList := AddItemToList(BlockTableTimeList,A_TickCount)
      ; close the table
      ;WinClose, ahk_id%vWinId%
      PostMessage, 0x112, 0xF060,,,ahk_id%vWinId%        
   }
;outputdebug, blocked table= %vTableName%
}


; ***************************************************************************


; update the BlockTableNameList and BlockTableTimeList, to see if we can remove any tables from the list
BlockTableListUpdate() 
{  
   global
   local vListLength, vBlockTime
   

   ; get the number of tables in the block table list
   vListLength := GetNumItemsInList(BlockTableNameList)
   
   ; we will work thru this list in reverse order
   loop, % vListLength
   {
      ; get the time this table was blocked
      vBlockTime := GetItemNFromList(BlockTableTimeList,vListLength - A_Index +1)
      ; if this table has been on the list longer than BlockTableMinutes, then remove it from the list
      if (((A_TickCount - vBlockTime)/60000) >   BlockTableMinutes)
      { 
         ; remove this item position from the list
         BlockTableNameList := RemoveItemNFromList(BlockTableNameList,vListLength - A_Index +1)
         BlockTableTimeList := RemoveItemNFromList(BlockTableTimeList,vListLength - A_Index +1)   
      }
   }

} 



; -------------------------------------------------------------------------------------------------------
   

; Update variables when a GUI variable changes
UpdateVariables:

   ; Copy GUI selections to variables
   Gui, 99:Default
   GUI, Submit, NoHide



   loop, %NumGroups%
   {
      ; make sure there is not a $ in the DesiredBigBlind
      ;StringReplace, DesiredBigBlind%A_index%, DesiredBigBlind%A_index%,$,,All
      ;GuiControl, , DesiredBigBlind%A_index%, % DesiredBigBlind%A_index%
      ;make sure there is not a $ in the DesiredMinPot
      ;StringReplace, DesiredMinPot%A_index%, DesiredMinPot%A_index%,$,,All
      ;GuiControl, , DesiredBigBlind%A_index%, % DesiredBigBlind%A_index%

      ; error checking to see if user made a mistake in seating size
      if (DesiredMinNumPlayers%A_index% > DesiredNumSeats%A_index%)
      {
         DesiredMinNumPlayers%A_index% := DesiredNumSeats%A_index%
         GuiControl, ChooseString, DesiredMinNumPlayers%A_index%, % DesiredMinNumPlayers%A_index%
      }
   }


   ; If the timer is enabled, then set the timer period in milliseconds
   if TimerEnabledFlag
       SetTimer, OpenAndCloseTables, % TimerPeriodMin * 60000

   ; SysListViewNum is a number that corresponds to the lobby window on the poker site
   ; This number varies as a function of the game type, and allows us to control the lobby window
   ; e.g. to control the Hold'em table list, we have to access the control:  SysListView323
   if (DesiredGames == "1-HOLD'EM")
      SysListViewNum:=323
   else if (DesiredGames == "2-OMAHA H/L")
      SysListViewNum:=324
   else if (DesiredGames == "3-OMAHA")
      SysListViewNum:=325
   else if (DesiredGames == "4-STUD H/L")
      SysListViewNum:=326
   else if (DesiredGames == "5-STUD")
      SysListViewNum:=327
   else if (DesiredGames == "6-RAZZ")
      SysListViewNum:=328

   ; return focus to this checkbox, to prevent accidentally changing other GUI controls when
   ;  the user is working with other windows and FTTO pops back up when the timer runs.
   ;  Then mouse scrolling and arrow keys won't change any of our controls, because focus will
   ;  be on this "dummy" control, and it won't matter
   ;  BUT, if we are on an edit box, then keep the focus there
   ControlGetFocus, Temp
   if (NOT InStr(Temp,"Edit"))
      GuiControl, Focus, KeepFocusHere
      
   ; allow these hot keys only on a FTP table
   Hotkey, IfWinActive, ahk_group GroupTableName
	Hotkey, %BlockTableControl%, BlockTable, UseErrorLevel On

Return


; -------------------------------------------------------------------------------------------------------


; Close All Tables
CloseAllTables:
   CloseAllTables()

   ; return focus to this checkbox, to prevent accidentally changing other GUI controls when
   ;  the user is working with other windows and FTTO pops back up when the timer runs.
   ;  Then scrolling actions won't change any of our controls, because focus will
   ;  be on this "dummy" control, and it won't matter
   ;    Gui, 99:Default
   ;GuiControl, Focus, KeepFocusHere

Return
; -------------------------------------------------------------------------------------------------------
; subroutine to close tables
CloseTables:
   CloseTables()

   ; return focus to this checkbox, to prevent accidentally changing other GUI controls when
   ;  the user is working with other windows and FTTO pops back up when the timer runs.
   ;  Then scrolling actions won't change any of our controls, because focus will
   ;  be on this "dummy" control, and it won't matter
   ;    Gui, 99:Default
   ;GuiControl, Focus, KeepFocusHere
Return

; -------------------------------------------------------------------------------------------------------
; subroutine to open tables
OpenTables:
   OpenTables()
   ; return focus to this checkbox, to prevent accidentally changing other GUI controls when
   ;  the user is working with other windows and FTTO pops back up when the timer runs.
   ;  Then scrolling actions won't change any of our controls, because focus will
   ;  be on this "dummy" control, and it won't matter
   ;    Gui, 99:Default
   ;GuiControl, Focus, KeepFocusHere
Return

; -------------------------------------------------------------------------------------------------------





; -------------------------------------------------------------------------------------------------------

; When exiting this program, save preferences.
; This is used to remove the table list and the ftto.semaphore if we are the last to exit.
99GuiClose:
ExitSub:
   ; variables used:   x,y,w,h

   ; Lets delete our own lock.
   FileDelete, Settings\ftto.%A_UserName%.%A_ComputerName%.lock

   ; If we can't see any other locks left (of other instances of this program (running in
   ;     other user areas, then delete the Settings\ftto.tablelist file and the Settings\ftto.semaphore.
   IfNotExist, Settings\*.lock
   {
      FileDelete, Settings\ftto.tablelist
      FileDelete, Settings\ftto.semaphore
   }

   ; save preferences in the .ini file
   ;get the current window position and size
   WinActivate, %Title%
   WinWaitActive, %Title%
   WinGetPos, x, y, w, h, %Title%
   w := w - 6                                           ; compensate for the GUI command
   IniWrite, %x%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, GuiX
   IniWrite, %y%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, GuiY

;outputdebug,   writing to ini file    MaxNumTablesInGroups= %MaxNumTablesInGroups%
   IniWrite , %MaxNumTablesInGroups%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, MaxNumTablesInGroups
   IniWrite , %DesiredGames%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredGames
   Loop, %NumGroups%
   {
      IniWrite , % EnabledGroup%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, EnabledGroup%A_index%      
      IniWrite , % DesiredTablesOpen%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredTablesOpen%A_index%
      IniWrite , % DesiredNumSeats%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredNumSeats%A_index%
      IniWrite , % DesiredMinNumPlayers%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinNumPlayers%A_index%
      IniWrite , % DesiredMaxNumPlayers%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMaxNumPlayers%A_index%
      IniWrite , % DesiredBigBlind%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredBigBlind%A_index%
      IniWrite , % DesiredType%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredType%A_index%
      IniWrite , % DesiredOptions%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredOptions%A_index%
      IniWrite , % DesiredMaxWaitNum%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMaxWaitNum%A_index%      
      IniWrite , % DesiredMinPot%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinPot%A_index%
      IniWrite , % DesiredMinPlyrPerFlop%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinPlyrPerFlop%A_index%
      IniWrite , % DesiredMinHandsPerHour%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMinHandsPerHour%A_index%  
      IniWrite , % DesiredMaxNumShortStacks%A_index%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DesiredMaxNumShortStacks%A_index%      
   }

   IniWrite , %AllowExtraOpeningsFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, AllowExtraOpeningsFlag
   IniWrite , %CloseLowerPriorityTablesFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseLowerPriorityTablesFlag
   IniWrite , %CloseHigherPriorityTablesFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseHigherPriorityTablesFlag      

   IniWrite , %CloseTablesWithFewFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesWithFewFlag
   IniWrite , %CloseTablesWithManyFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesWithManyFlag
   IniWrite , %CloseTablesNotMeetingCriteriaFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesNotMeetingCriteriaFlag   
   IniWrite , %CloseTablesNotInLobbyFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesNotInLobbyFlag
   IniWrite , %CloseTablesNotInEnabledGroupFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesNotInEnabledGroupFlag
;   IniWrite , %CloseTablesInOtherUserAreaFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CloseTablesInOtherUserAreaFlag
   IniWrite , %DoNotCloseTablesThatAreMaximizedFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DoNotCloseTablesThatAreMaximizedFlag

   IniWrite , %MinimizeTablesFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, MinimizeTablesFlag
   IniWrite , %MinimizeLobbyFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, MinimizeLobbyFlag
   IniWrite , %TimerPeriodMin%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, TimerPeriodMin
   
   ; Misc
   IniWrite , %CodeType%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CodeType   
   IniWrite , %CopyObservedFilesFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, CopyObservedFilesFlag  
   IniWrite , %SourceFolder%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, SourceFolder
   IniWrite , %DestinationFolder%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, DestinationFolder
   IniWrite , %ChangeObservedFilesSuffixFlag%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, ChangeObservedFilesSuffixFlag   
   IniWrite , %BlockTableControl%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, BlockTableControl
   IniWrite , %BlockTableMinutes%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, BlockTableMinutes
   IniWrite , %ShortStackSizeBB%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, ShortStackSizeBB   
   IniWrite , %SharkListEnabled%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, SharkListEnabled
   IniWrite , %SharkList%, Settings\ftto.%A_UserName%.%A_ComputerName%.ini, Prefs, SharkList

   
  
   
ExitApp  ; The only way for an OnExit script to terminate itself is to use ExitApp in the OnExit subroutine.



; =======================================================================================================
;     FUNCTIONS
; =======================================================================================================





; -------------------------------------------------------------------------------------------------------



; Close Tables that:
;     1. empty or that are no longer open in the lobby (if enabled)
;     2. no longer have enough players at the table (if enabled)
;     3. are open in other user areas (if enabled)
;     4. tables in lobby but not part of any group (if enabled)
;  do not close tables that we are seated at
;  do not close tables that are visible (if enabled)

CloseTables()
{
   ; make all global vars available in this function
   global
   ; define local variables here
   local vLobbyId, vTableIdList, vLobbyTableString, vTableId, vTableName, vTablePosInString
   local vTablePosInString1, vTableBigBlind, vTableType, vTableOptions, vTableNumPlayers, vTableNumSeats
   local vTableInGroupFlag, vFlag, vLastWinId
   local vThisTableString, vTableArray, vNewLine




   ; find out how may tables are currently open in each group
   ;UpdateNumTablesOpen()
;outputdebug, in CloseTables0
   DisplayStatus("Closing Tables")
;outputdebug, in CloseTables1
   ; get the Lobby ID, incase the lobby has been closed an re-opened since last time
   ;WinGet, vLobbyId, ID, ahk_group GroupLobbyName                       ; get the lobby ID
   WinGet, vLobbyId, ID, ahk_class FTCLobby
   ;make a list of all the open table IDs, excluding Lobby
   ;WinGet puts the table count in the variable TableIdList,
   WinGet, vTableIdList, List, ahk_group GroupTableName

   ;read in the entire Lobby table list into a string...  so we can see if our tables are still open in lobby
   ControlGet, vLobbyTableString, List,, SysListView%SysListViewNum%, ahk_id%vLobbyId%


   ; loop through all of the open tables
   Loop, %vTableIdList%
   {
      ; find the next ID of the next open table
      StringTrimRight, vTableId, vTableIdList%A_Index%, 0

      vTableName := TableRingName(vTableId)

      ; if we are not to close maximized tables, and this table is maximized, then skip this table
      If DoNotCloseTablesThatAreMaximizedFlag
      {
         ; check if this table is NOT minimized, if so then ignore it
         WinGet, vFlag, MinMax, ahk_id%vTableId%
         if (vFlag == 0)
            continue
      }
      
      ; if the hero is seated, then skip this table
      if HeroSeated(vTableId)
         continue


      ; check if this open table is open in another user area AND if user wants us
      ; to close these type of tables. If it is, then close it.
      if (CloseTablesInOtherUserAreaFlag AND (CheckIfTableisOpenInOtherUserArea(vTableName) == 1))
      {
         vLastWinId := WinActive("A")
         ;WinClose, ahk_id%vTableId%
         PostMessage, 0x112, 0xF060,,,ahk_id%vTableId%           
         WinWaitClose, ahk_id%vTableId%, , WinCloseTime
         WinActivate, ahk_id%vLastWinId%

         Continue
      }


      ;Check if TableName in the big LobbyTableString
      ;     returns the character position of the TableName in the LobbyTableString
      ;     returns 0 if it is not in the Lobby
      vTablePosInString := InStr(vLobbyTableString, vTableName,1)

;outputdebug, %vTableName%  from list of tables   position in big string=%vTablePosInString%

      ; Close this table,  IF
      ;     1. user wants us to close tables not in current lobby (by flag being set)
      ;     2. AND the table is NOT in the current lobby
      ;   this will close empty tables that are no longer in the lobby.
      If CloseTablesNotInLobbyFlag  AND  (NOT vTablePosInString)
      {
         vLastWinId := WinActive("A")
         PostMessage, 0x112, 0xF060,,,ahk_id%vTableId%         
         ;WinClose, ahk_id%vTableId%                               ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!    maybe try other closing table method  ??????????????????
         WinWaitClose, ahk_id%vTableId%, , WinCloseTime
         WinActivate, ahk_id%vLastWinId%
         Continue
      }

      ; see if we have to close tables with too few players, or tables that are not part of a "active" group.
      ; First verify that
      ;     1. the table is in the lobby (TablePosInString)
      ;     2. AND   (CloseTablesWithFewFlag OR CloseTablesNotInEnabledGroupFlag)
      If ((CloseTablesWithFewFlag OR CloseTablesNotInEnabledGroupFlag OR CloseTablesNotMeetingCriteriaFlag) AND vTablePosInString )
      {

         ; we now need to extract the Stakes, Type, and NumberSeats, etc.  from the string
         ;     to see if they match one of our groups, so we see if we should delete the table
         ;     if there are too few players at the table.
         
         
         ;  vTablePosInString is currently pointing at the beginning of the table name.
         ;        find the end of the string, by searching for the `n character
         ;        extract that part of the string for all of the table items, and then extract out the various items
         
         ; find the end of this table in the big string of this string
         vNewLine = `n
         StringGetPos, vTablePosInString1, vLobbyTableString, `n,,vTablePosInString
         vTablePosInString1 := vTablePosInString1 + 1                ; convert to 
;         vTablePosInString1 := InStr(vLobbyTableString,vNewLine,0, vTablePosInString)    
         ; extract out just this table's string of info (starts at the beginning of the table name, goes to right before the new line char `n)
         StringMid, vThisTableString, vLobbyTableString, vTablePosInString, vTablePosInString1 - vTablePosInString
      
      
;outputdebug, vThisTableString=%vThisTableString%     vTablePosInString=%vTablePosInString%         vTablePosInString1=%vTablePosInString1%
      
         ; get the information about the next table in the lobby table list
         StringSplit, vTableArray, vThisTableString, %A_Tab%

;outputdebug   %vTableArray1%***%vTableArray2%***%vTableArray3%***%vTableArray4%***%vTableArray5%***%vTableArray6%***%vTableArray7%

         vTableName := vTableArray1                                                 ; save the table name
         vTableBigBlind := vTableArray2                                               ; get the table stakes
         ; to get just the big blind amount, trim off everything on the left up to through the "/$"
         StringRight, vTableBigBlind, vTableBigBlind, StrLen(vTableBigBlind) - InStr(vTableBigBlind,"/$") - 1

         vTableType := substr(vTableArray3,1,2)                                                 ; get the table type (NL, PL, FL) which is the first 2 characters of  vTableArray4

         ; the table options are also contained in vTableArray4
         ; vTableArray4 consists of 7 characters
         ; NL6ATED
         ; options are
         ; 6 for 6 players
         ; 2 for 2 players
         ; A Antes
         ; D double stack
         ; C capped game
         ; E educational table
         ; T speed  NOTE: we use "S" in our options for this to make it easier for the user to remember speed

         ; Note that we concatenate these options in alphabetical order, so that if full tilt added some other options together, we'll list them in alphabetical order.

         vTableOptions := ""
         if instr(vTableArray3,"A",1)
            vTableOptions := vTableOptions . "A"
         if instr(vTableArray3,"C",1)
            vTableOptions := vTableOptions . "C"
         if instr(vTableArray3,"D",1)
            vTableOptions := vTableOptions . "D"
         if instr(vTableArray3,"E",1)
            vTableOptions := vTableOptions . "E"
         if instr(vTableArray3,"T",1)
            vTableOptions := vTableOptions . "S"                  ; Note we substitute and S for the T that full tilts uses for the speed tables

         ; if there weren't any of these options, then we set vTableOptions to none
         if NOT vTableOptions
            vTableOptions := "None"
      
         
         
         
         
         
         
         ; remove the happy hour string from the players string if it is there
         StringReplace, vTableArray4, vTableArray4,%A_Space%H,,All            
         
         StringLeft, vTableNumPlayers, vTableArray4, 1                              ; get the number of players at table
         StringRight, vTableNumSeats, vTableArray4, 1                               ; get num of seats at table
         vTableWaitNum := vTableArray5                                              ; get num of players in wait list
         StringRight, vTableAvgPot, vTableArray6, StrLen(vTableArray6) - 1          ; get the avg pot size
         StringLeft, vTablePlyrPerFlop, vTableArray7, StrLen(vTableArray7) - 1          ; get the % players per flop
         vTableHandsPerHour := vTableArray8                                       ; get the number of hands per hour
         StringReplace, vTableHandsPerHour, vTableHandsPerHour,>,,All                ; if there is a > char in there, then replace it with NULL     





         
;outputdebug,  TableName=%vTableName%`nstakes=%vTableBigBlind%`ntype=%vTableType%`noptions=%vTableOptions%`n#players=%vTableNumPlayers%`nseats=%vTableNumSeats%`navgpot=%vTableAvgPot%`nPlyrs/pot=%vTablePlyrPerFlop%`nhands/hr=%vTableHandsPerHour%`n         


         
/*         
   NOTE: this was the old way that I extracted out the info from the big string... the above method uses the array function to break it up more
   
   
         ; extract the Stakes (actually only the big blind amount)
         ; find the position of the next tab char
         vTablePosInString := InStr(vLobbyTableString,"`t",0, vTablePosInString)
         ; find the position of the /$
         vTablePosInString := InStr(vLobbyTableString,"/$",0, vTablePosInString)
         ; and get the next position of the tab char
         vTablePosInString1 := InStr(vLobbyTableString,"`t",0,vTablePosInString)
         ; The Stakes (the big blind amount) are inbetween the /$ and the next tab character
         StringMid, vTableBigBlind, vLobbyTableString, vTablePosInString + 2, vTablePosInString1 - vTablePosInString - 2

         ; extract the Type (e.g. NL, Limit, etc)
         ; set the position if the current tab character
         vTablePosInString := vTablePosInString1
         ; and get the next position of the tab char
         vTablePosInString1 := InStr(vLobbyTableString,"`t",0,vTablePosInString + 1)
         ; The TableType are inbetween these two tab characters
         StringMid, vTableType, vLobbyTableString, vTablePosInString + 1, vTablePosInString1 - vTablePosInString - 1



         ; NOTE we shouldn't have to worry about the possibility of the happy hour " H" being tagged to the end of this string
         ;     because of the way that were are extracting the number of players and seats at the table
         
         ; extract the number of players at this table
         ; set the position if the last found tab character
         vTablePosInString := vTablePosInString1
         StringMid, vTableNumPlayers, vLobbyTableString, vTablePosInString + 1, 1

         ; extract the Num Seats for this table
         StringMid, vTableNumSeats, vLobbyTableString, vTablePosInString + 3, 1


         ; extract the number on waiting list
         
         ; extract the Average pot size
         
         ; extract the number of players per flop
         
         ; extract the numbrr of hands per hour



         ; get the table options for this table
         if (instr(vTableName,"deep"))
            vTableOptions := "deep"
         else
            vTableOptions := "None"  
*/



         ; Close this table, IF
         ;     1. user wants us to close tables that have too few of players (by flag being set)
         ;     3. AND this table is in one of our groups, (check #seats, stakes, and table type below)
         ;     4. AND this table has too few players at it (this is checked a few lines down)
         If (CloseTablesWithFewFlag )
         {
            ; loop through the groups, and see if there is a match with the table we have here
            Loop, %NumGroups%
            {
               ; make sure this group is an active group, else continue
               if (EnabledGroup%A_index% == 0)
                  continue

               ; I removed this in version 1.13 since FT changed their options -->   AND ((vTableOptions == DesiredOptions%A_index%) OR (DesiredOptions%A_index% == "All")

               ; if this tables matches any group's criteria, and there are too few players ,
               ;      then close this table
               If (      (vTableBigBlind == DesiredBigBlind%A_index%)
                     AND (vTableType == DesiredType%A_index%)
                     AND (vTableOptions == DesiredOptions%A_index%)
                     AND (vTableNumSeats == DesiredNumSeats%A_index%)
                     AND (vTableNumPlayers < DesiredMinNumPlayers%A_index%)       )
               {
               
;outputdebug, closing table here1
                  vLastWinId := WinActive("A")
                  PostMessage, 0x112, 0xF060,,,%vTableName%
                  ;WinClose, %vTableName%                                ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   we could close table by other method   ??????????????????????
                  WinWaitClose, ahk_id%vTableId%, , WinCloseTime
                  WinActivate, ahk_id%vLastWinId%
               }
            }
         }

         ; Close this table, IF
         ;     1. user wants us to close tables that have too many players (by flag being set)
         ;     3. AND this table is in one of our groups, (check #seats, stakes, and table type below)
         ;     4. AND this table has many players at it (this is checked a few lines down)
         If (CloseTablesWithManyFlag )
         {
            ; loop through the groups, and see if there is a match with the table we have here
            Loop, %NumGroups%
            {
               ; make sure this group is an active group, else continue
               if (EnabledGroup%A_index% == 0)
                  continue

               ; I removed this line from below in version 1.13, after FT came out with more options -->   AND ((vTableOptions == DesiredOptions%A_index%) OR (DesiredOptions%A_index% == "All"))

               ; if this tables matches any group's criteria, and there are too few players ,
               ;      then close this table
               If (      (vTableBigBlind == DesiredBigBlind%A_index%)
                     AND (vTableType == DesiredType%A_index%)
                     AND (vTableOptions == DesiredOptions%A_index%)
                     AND (vTableNumSeats == DesiredNumSeats%A_index%)
                     AND (vTableNumPlayers > DesiredMaxNumPlayers%A_index%)       )
               {
;outputdebug, closing table here2
                  vLastWinId := WinActive("A")
                  PostMessage, 0x112, 0xF060,,,%vTableName%
                  ;WinClose, %vTableName%                                ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   we could close table by other method   ??????????????????????
                  WinWaitClose, ahk_id%vTableId%, , WinCloseTime
                  WinActivate, ahk_id%vLastWinId%
               }
            }
         }


         ; Close this table, IF
         ;     1. user wants us to close tables that have fallen below any of the specified criteria (by flag being set, that is the checkbox is checked)
         ;     3. AND this table is in one of our groups, (check #seats, stakes, options, and table type below)
         ;     4. AND any other major criteria as fallen out of it desired range
         If (CloseTablesNotMeetingCriteriaFlag )
         {
            ; loop through the groups, and see if there is a match with the table we have here
            Loop, %NumGroups%
            {
               ; make sure this group is an active group, else continue
               if (EnabledGroup%A_index% == 0)
                  continue


               ; if any of these table parameters are blank, then set them equal to the desired so that we make a match below
               if (vTableWaitNum == "")
                  vTableWaitNum := DesiredMaxWaitNum%A_index%
               if (vTableAvgPot == "")
                  vTableAvgPot := DesiredMinPot%A_index%
               if (vTablePlyrPerFlop == "")
                  vTablePlyrPerFlop := DesiredMinPlyrperFlop%A_index%
               if (vTableHandsPerHour == "")
                  vTableHandsPerHour := DesiredMinHandsPerHour%A_index%



               ; removed in version 1.13 after FT added more options -->    AND ((vTableOptions == DesiredOptions%A_index%)   OR (DesiredOptions%A_index% == "All"))

               ; if this tables matches the group's criteria, and there are too few players at it,
               ;      then close this table
               If (         (vTableBigBlind == DesiredBigBlind%A_index%)
                        AND (vTableType == DesiredType%A_index%)
                        AND ((vTableOptions == DesiredOptions%A_index%))
                        AND (vTableNumSeats == DesiredNumSeats%A_index%)
                        AND (          (vTableNumPlayers < DesiredMinNumPlayers%A_index%)
                                    OR (vTableNumPlayers > DesiredMaxNumPlayers%A_index%)
                                    OR (vTableAvgPot < DesiredMinPot%A_index%)   
                                    OR (vTablePlyrPerFlop < DesiredMinPlyrperFlop%A_index%)
                                    OR (vTableHandsPerHour < DesiredMinHandsPerHour%A_index%)       )    )
               {
;outputdebug, closing table here3
                  vLastWinId := WinActive("A")
                  PostMessage, 0x112, 0xF060,,,%vTableName%
                  ;WinClose, %vTableName%                                ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   we could close table by other method   ??????????????????????
                  WinWaitClose, ahk_id%vTableId%, , WinCloseTime
                  WinActivate, ahk_id%vLastWinId%
               }
            }
         }
      


     
;outputdebug,  TableName=%vTableName%`nstakes=%vTableBigBlind%`ntype=%vTableType%`noptions=%vTableOptions%`n#players=%vTableNumPlayers%`nseats=%vTableNumSeats%`navgpot=%vTableAvgPot%`nPlyrs/pot=%vTablePlyrPerFlop%`nhands/hr=%vTableHandsPerHour%`n      


         ; Close this table, IF
         ;     1. user wants us to close tables that are not in any enabled group (CloseTablesNotInEnabledGroupFlag)
         ;     3. AND this table is NOT in one of our enabled groups, (check #seats, stakes, and table type below)
         If (CloseTablesNotInEnabledGroupFlag)
         {


            vTableInGroupFlag := 0
            ; loop through the groups, and see if there is a match with the table we have here
            Loop, %NumGroups%
            {

               ; removed in version 1.13 below (after full tilt added more option) -->   AND ((vTableOptions == DesiredOptions%A_index%)  OR (DesiredOptions%A_index% == "All"))

               ; if this tables matches any group's criteria and the group is enabled, then set a flag so we don't close it
               ;      then close this table
               If (      (vTableBigBlind == DesiredBigBlind%A_index%)
                     AND (vTableType == DesiredType%A_index%)
                     AND ((vTableOptions == DesiredOptions%A_index%))
                     AND (vTableNumSeats == DesiredNumSeats%A_index%)   
                     AND (EnabledGroup%A_index%)                         )
               {
                  vTableInGroupFlag := 1
                  break
               }
            }

            ; if the table was not found in any enabled group, then delete it
            if NOT vTableInGroupFlag
            {
;outputdebug, closing table here4
                  vLastWinId := WinActive("A")
                  PostMessage, 0x112, 0xF060,,,%vTableName%
                  ;WinClose, %vTableName%                                         ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!   we could close by other method   ??????????????????
                  WinWaitClose, ahk_id%vTableId%, , WinCloseTime
                  WinActivate, ahk_id%vLastWinId%

            }
         }
      }
   }

   ; minimize the lobby if user's flag is set
   if MinimizeLobbyFlag
      PostMessage, 0x112, 0xF020,,,ahk_class FTCLobby              ;        WinMinimize, ahk_group GroupLobbyName
      
   ; Update the table names, just in case closed any.
   RefreshNames()

   ; find out how may tables are currently open in each group
   ;UpdateNumTablesOpen()

   ; set and display our current status
   if TimerEnabledFlag
      DisplayStatus("Waiting For Timer")
   else
      DisplayStatus("Stopped")


}

; --------------------------------------------------------------------------------------

; Close One table in group that is in vGroup:
;  do not close tables that we are seated at
;  do not close tables that are visible (if enabled)
;
;  if vGroup == 1-8, then close one table in that group (if possible)
;        return 1 if successful, else return 0
CloseTableInGroup(vGroup)
{
   ; make all global vars available in this function
   global
   ; define local variables here
   local vLobbyId, vTableIdList, vLobbyTableString, vTableId, vTableName, vTablePosInString
   local vTablePosInString1, vTableBigBlind, vTableType, vTableNumPlayers, vTableNumSeats
   local vTableInGroupFlag, vFlag, vLastWinId, vTempType


   ; verify that vGroup is enabled, if not return 0
   if (EnabledGroup%vGroup% == 0)
      return 0   

   ; find out how may tables are currently open in each group
   ;UpdateNumTablesOpen()
   
   ; don't need to do this, because this routine is called directly from the OpenTables functions, and it is already done
   ;DisplayStatus("Closing Tables")

   ; get the Lobby ID, incase the lobby has been closed an re-opened since last time
   ;WinGet, vLobbyId, ID, ahk_group GroupLobbyName                       ; get the lobby ID
   WinGet, vLobbyId, ID, ahk_class FTCLobby
   ;make a list of all the open table IDs, excluding Lobby
   ;WinGet puts the table count in the variable TableIdList,
   WinGet, vTableIdList, List, ahk_group GroupTableName

   ;read in the entire Lobby table list into a string...  so we can see if our tables are still open in lobby
   ControlGet, vLobbyTableString, List,, SysListView%SysListViewNum%, ahk_id%vLobbyId%


   ; loop through all of the open tables
   Loop, %vTableIdList%
   {
      ; find the next ID of the next open table
      StringTrimRight, vTableId, vTableIdList%A_Index%, 0

      vTableName := TableRingName(vTableId)

      ; if we are not to close maximized tables, and this table is maximized, then skip this table
      If DoNotCloseTablesThatAreMaximizedFlag
      {
         ; check if this table is NOT minimized, if so then ignore it
         WinGet, vFlag, MinMax, ahk_id%vTableId%
         if (vFlag == 0)
            continue
      }
      
      ; if the hero is seated, then skip this table
      if HeroSeated(vTableId)
         continue

/* it is not our job to close this type of table

      ; check if this open table is open in another user area AND if user wants us
      ; to close these type of tables. If it is, then close it.
      if (CloseTablesInOtherUserAreaFlag AND (CheckIfTableisOpenInOtherUserArea(vTableName) == 1))
      {
         vLastWinId := WinActive("A")
         WinClose, ahk_id%vTableId%
         WinWaitClose, ahk_id%vTableId%, , WinCloseTime
         WinActivate, ahk_id%vLastWinId%
         Continue
      }
*/



      ;Check if TableName in the big LobbyTableString
      ;     returns the character position of the TableName in the LobbyTableString
      ;     returns 0 if it is not in the Lobby
      vTablePosInString := InStr(vLobbyTableString, vTableName,1)




/* it is not our job to close this type of table
      ; Close this table,  IF
      ;     1. user wants us to close tables not in current lobby (by flag being set)
      ;     2. AND the table is NOT in the current lobby
      ;   this will close empty tables that are no longer in the lobby.
      If CloseTablesNotInLobbyFlag  AND  (NOT vTablePosInString)
      {
         vLastWinId := WinActive("A")
         WinClose, ahk_id%vTableId%
         WinWaitClose, ahk_id%vTableId%, , WinCloseTime
         WinActivate, ahk_id%vLastWinId%
     
         Continue
      }
*/


      ; verify that this table is in the lobby string
      If (vTablePosInString)
      {

         ; we now need to extract the Stakes, Type, and NumberSeats from the string
         ;     to see if they match one of our groups, so we see if we should delete the table
         ;     if there are too few players at the table.

         ; extract the Stakes (actually only the big blind amount)
         ; find the position of the next tab char
         vTablePosInString := InStr(vLobbyTableString,"`t",0, vTablePosInString)
         ; find the position of the /$
         vTablePosInString := InStr(vLobbyTableString,"/$",0, vTablePosInString)
         ; and get the next position of the tab char
         vTablePosInString1 := InStr(vLobbyTableString,"`t",0,vTablePosInString)
         ; The Stakes (the big blind amount) are inbetween the /$ and the next tab character
         StringMid, vTableBigBlind, vLobbyTableString, vTablePosInString + 2, vTablePosInString1 - vTablePosInString - 2


         ; extract the entire Type string, which contains the type and options
         ; set the position to the 1st character of the TYPE
         vTablePosInString := vTablePosInString1 + 1
         ; and get the next position of the tab char
         vTablePosInString1 := InStr(vLobbyTableString,"`t",0,vTablePosInString)
         ; get the entire type string (which contains type and options)
         vTempType := substr(vLobbyTableString,vTablePosInString,vTablePosInString1 - vTablePosInString)


         vTableType := substr(vTempType,1,2)                                                 ; get the table type (NL, PL, FL) which is the first 2 characters of  vTempType

         ; the table options are also contained in vTempType
         ; vTempType consists of 7 characters
         ; NL6ATED
         ; options are
         ; 6 for 6 players
         ; 2 for 2 players
         ; A Antes
         ; D double stack
         ; C capped game
         ; E educational table
         ; T speed  NOTE: we use "S" in our options for this to make it easier for the user to remember speed

         ; Note that we concatenate these options in alphabetical order, so that if full tilt added some other options together, we'll list them in alphabetical order.

         vTableOptions := ""
         if instr(vTempType,"A",1)
            vTableOptions := vTableOptions . "A"
         if instr(vTempType,"C",1)
            vTableOptions := vTableOptions . "C"
         if instr(vTempType,"D",1)
            vTableOptions := vTableOptions . "D"
         if instr(vTempType,"E",1)
            vTableOptions := vTableOptions . "E"
         if instr(vTempType,"T",1)
            vTableOptions := vTableOptions . "S"                  ; Note we substitute and S for the T that full tilts uses for the speed tables

         ; if there weren't any of these options, then we set vTableOptions to none
         if NOT vTableOptions
            vTableOptions := "None"



         ; extract the number of players at this table
         ; set the position if the last found tab character
         vTablePosInString := vTablePosInString1
         StringMid, vTableNumPlayers, vLobbyTableString, vTablePosInString + 1, 1

         ; extract the Num Seats for this table
         StringMid, vTableNumSeats, vLobbyTableString, vTablePosInString + 3, 1


         ; if this table matches our vGroup settings, then close the table
         If (      (vTableBigBlind == DesiredBigBlind%vGroup%)
               AND (vTableType == DesiredType%vGroup%)
               AND (vTableOptions == DesiredOptions%vGroup%)
               AND (vTableNumSeats == DesiredNumSeats%vGroup%)   )
         {
;outputdebug, closing table here5
            vLastWinId := WinActive("A")
            ;WinClose, %vTableName%
            PostMessage, 0x112, 0xF060,,,%vTableName%
            WinWaitClose, ahk_id%vTableId%, , WinCloseTime
            WinActivate, ahk_id%vLastWinId%
            
            ; minimize the lobby if user's flag is set
            if MinimizeLobbyFlag
               PostMessage, 0x112, 0xF020,,,ahk_class FTCLobby              ;        WinMinimize, ahk_group GroupLobbyName
            
            return 1
            
         }
      }
   }
   ; we were not able to close a table in this group for some reason
   return 0
}



; -------------------------------------------------------------------------------------------------------

; see if we can close a table in a higher or lower priority group
; return 1 if successful, 0 otherwise
CloseTableInOtherGroup(vThisGroup)
{
   global
   local vGroup
   

;EnabledGroup1   AllowExtraOpeningsFlag   CloseLowerPriorityTablesFlag    CloseHigherPriorityTablesFlag
   ; see if we can close a lower priority table
   if CloseLowerPriorityTablesFlag
   {      
      
      vGroup := vThisGroup
      loop
      {
         vGroup++
         ;outputdebug, Going Lower: vGroup= %vGroup%         
         if (vGroup > NumGroups)
            break
         ; check if we are over our quota of this type of table
         if (NumTablesOpen%vGroup% > DesiredTablesOpen%vGroup%)
         {
            if CloseTableInGroup(vGroup)
               return 1
            ; else we continue   
         }
      }
   }

   ; see if we can close a higher priority table, but only if we are below quota on our table
   if CloseHigherPriorityTablesFlag
   {
      ; if we have our quota for this group, then return (don't close a higher priority table just to open an extra lower priority table)
      if (NumTablesOpen%vThisGroup% >= DesiredTablesOpen%vThisGroup%)
         return 0
         
      vGroup := vThisGroup
      loop
      {
         vGroup--
         ;outputdebug, Going Higher: vGroup= %vGroup%         
         if (vGroup < 1)
            break
         ; check if we are over our quota of this type of table
         if (NumTablesOpen%vGroup% > DesiredTablesOpen%vGroup%)
         {
            if CloseTableInGroup(vGroup)
               return 1
            ; else we continue               
         }
      }
   }
   ; we were not able to close a table
   return 0
}



; -------------------------------------------------------------------------------------------------------


; Close All Tables (except those that you are seated at)
CloseAllTables()
{
   ; make all global vars available in this function
   global
   ; define local variables here
   local vTableIdList, vTableId, vFlag

   DisplayStatus("Closing Tables")

   ;make a list of all the open table IDs, excluding Lobby
   ;WinGet puts the table count in the variable TableIdList,
   WinGet, vTableIdList, List, ahk_group GroupTableName

   ; loop through all of the open tables
   Loop, %vTableIdList%
   {

      ; find the next ID of the next open table
      StringTrimRight, vTableId, vTableIdList%A_Index%, 0


      ; check if we are seated at this table, by seeing if the SitOutNextHand button is visible
      ; if seated, then ignore this table
;      ControlGet, vFlag, Visible,,FTCButton1, ahk_id%vTableId%
;      if (vFlag)
;         Continue

      if HeroSeated(vTableId)
         continue

;outputdebug, closing table here6
      ; close this table
      PostMessage, 0x112, 0xF060,,,ahk_id%vTableId%      
      ;WinClose, ahk_id%vTableId%
      WinWaitClose, ahk_id%vTableId%, , WinCloseTime
      Continue
   }


   ; Update the table names
   RefreshNames()

   ; find out how may tables are currently open in each group
   ;UpdateNumTablesOpen()

   ; set and display our current status
   if TimerEnabledFlag
      DisplayStatus("Waiting For Timer")
   else
      DisplayStatus("Stopped")


}

; -------------------------------------------------------------------------------------------

; un minimize all tables
RestoreTables()
{

   ; make all global vars available in this function
   global
   ; define local variables here
   local vTableIdList, vTableId, vFlag

   ;DisplayStatus("Closing Tables")

   ;make a list of all the open table IDs, excluding Lobby
   ;WinGet puts the table count in the variable TableIdList,
   WinGet, vTableIdList, List, ahk_group GroupTableName

   ; loop through all of the open tables
   Loop, %vTableIdList%
   {

      ; find the next ID of the next open table
      StringTrimRight, vTableId, vTableIdList%A_Index%, 0


      ; check if we are seated at this table, by seeing if the SitOutNextHand button is visible
      ; if seated, then ignore this table
;      ControlGet, vFlag, Visible,,FTCButton1, ahk_id%vTableId%
;      if (vFlag)
;         Continue

;      if HeroSeated(vTableId)
;         continue


      ; check if this table is minimized
      WinGet, vFlag, MinMax, ahk_id%vTableId%
      if (vFlag == -1)
      {

         ; unminimize this table
         WinRestore, ahk_id%vTableId%
      }
   }


}


; -------------------------------------------------------------------------------------------

; minimize all tables, except if hero is seated at the table
MinimizeTables()
{

   ; make all global vars available in this function
   global
   ; define local variables here
   local vTableIdList, vTableId, vFlag

   ;DisplayStatus("Closing Tables")

   ;make a list of all the open table IDs, excluding Lobby
   ;WinGet puts the table count in the variable TableIdList,
   WinGet, vTableIdList, List, ahk_group GroupTableName

   ; loop through all of the open tables
   Loop, %vTableIdList%
   {

      ; find the next ID of the next open table
      StringTrimRight, vTableId, vTableIdList%A_Index%, 0


      ; check if we are seated at this table, by seeing if the SitOutNextHand button is visible
      ; if seated, then ignore this table
;      ControlGet, vFlag, Visible,,FTCButton1, ahk_id%vTableId%
;      if (vFlag)
;         Continue

      if HeroSeated(vTableId)
         continue


      ; minimize this table
      WinMinimize, ahk_id%vTableId%


   }


}

; -------------------------------------------------------------------------------------------




; display our current status on the GUI
DisplayStatus(pString="")
{
   global
   static LastStatus
   
   
;outputdebug, in display status
   
   if pString
      LastStatus := pString

   ; save the currently active window
;   vWinId := WinActive("A")

   ; find the number of open tables in each group
   UpdateNumTablesOpen()

   ; display the number of open tables
   Gui, 99:Default
   GuiControl,,Status1, Total Open:%NumTablesOpen%  Total Open In Groups:%NumTablesOpenInGroups%`nA:%NumTablesOpen1%  B:%NumTablesOpen2%  C:%NumTablesOpen3%  D:%NumTablesOpen4%  E:%NumTablesOpen5%  F:%NumTablesOpen6%  G:%NumTablesOpen7%  H:%NumTablesOpen8%
   ; display our current operation. e.g.  Stopped, Waiting For Timer, Opening Tables.... etc.
   GuiControl,,Status, Status: %LastStatus%
   
   
   ; return to the previously active window
;   WinActivate, ahk_id%vWinId%
}

; -------------------------------------------------------------------------------------------------------



Opentables()
{
   ; make all global vars available in the functions
   global
   ; define local variables here
   local vLobbyId, vThisGroup
   local vTableArray, vTableName, vTableBigBlind, vTableType, vTableOptions, vTableNumPlayers, vTablePlyrPerFlop, vTableHandsPerHour
   local vTableNumSeats, vTableAvgPot, vTableNameList
   local vLobbyTableString, vFocusedPos, vTablePos, vFocusedTableName, vLastTableId
   local vTableWaitNum                          ; number of players in wait list
   local vPass                                  ; the current pass we are on
   local vPlayerListWindow, vPlayerList, vStackList, vPlayerListFields, vStackSize, vNumShortStacks, vNumStacks, vPlayer, vFoundSharkFlag
   local vTableData, vLobbyTableString1


;outputdebug, in OpenTables 0


; save the currently active window so we can reactivate it at end of this function
vLastWinId := WinActive("A") 

   ; get the Lobby ID, incase the lobby has been closed an re-opened since last time
;   WinGet, vLobbyId, ID, ahk_group GroupLobbyName                       ; get the lobby ID
   WinGet, vLobbyId, ID, ahk_class FTCLobby                       ; get the lobby ID

;outputdebug, vLobbyId=%vLobbyId%

   ; find out how may tables are currently open in each group
   ;UpdateNumTablesOpen()

;outputdebug, in OpenTables 1
   ; show the number of tables open
   DisplayStatus("Opening Tables")
;outputdebug, in OpenTables 2
   ; we will loop for 2 passes...
   ; Pass 1 is to open tables for each group, trying to fill up the group
   ; Pass 2 is to open additional tables beyond a groups quota, trying to get to MaxNumTablesInGroups
   Loop, 2
   {
      vPass := A_Index
      
      ; the 2nd pass thru this allows us to open extra tables in each group... see if they are allowed
      ; check if we allow extra tables to be opened in each group in vPass == 2
      if ((!AllowExtraOpeningsFlag) AND (vPass == 2))
         break


      ; Loop through all the groups to open table in group 1 first, then 2, etc.
      Loop, %NumGroups%
      {
         ; save this a_index, as we will need it inside of another Loop command
         vThisGroup := a_index
         
         ; if this group is not enabled, then continue to next group
         if (! EnabledGroup%vThisGroup%)
            continue
   
         ;if we are at max limit of tables open
         ;If (NumTablesOpenInGroups >= MaxNumTables)
         ;  break   

   
         ; read the entire lobby table list
         ControlGet, vLobbyTableString, List,, SysListView%SysListViewNum%, ahk_id%vLobbyId%
;ControlGet, vLobbyTableString, List,, SysListView329, ahk_id%vLobbyId%                            ; mixed games is 329
;outputdebug, tablestring= %vLobbyTableString%      vLobbyId=%vLobbyId%
;return
         ; Loop thru all the tables in this list, and open those tables that meet this groups criteria
         Loop, Parse, vLobbyTableString, `n
         {
            ;if we are at max limit of tables open
            ;If (NumTablesOpenInGroups >= MaxNumTables)
            ;   break
         
         
            ;outputdebug, actual=  %NumTablesOpen1%
            ;outputdebug, desired= %DesiredTablesOpen1%
            
            ; if we are on first pass, and we have our quota for this group, then break out to next group
            if ((vPass == 1) AND (NumTablesOpen%vThisGroup% >= DesiredTablesOpen%vThisGroup%))
                  break

            ; save the entire string of data for this table... so we can look for a match later
            vTableData := A_LoopField
                        
         
            ; get the information about the next table in the lobby table list
            StringSplit, vTableArray, A_LoopField, %A_Tab%
   

;outputdebug %vTableArray1%***%vTableArray2%***%vTableArray3%***%vTableArray4%***%vTableArray5%***%vTableArray6%***%vTableArray7%
;outputdebug %vTableArray4%        %vTableArray2%
;continue
            vTableName := vTableArray2                                                 ; save the table name
            vTableBigBlind := vTableArray3                                               ; get the table stakes
            ; to get just the big blind amount, trim off everything on the left up to through the "/$"
            StringRight, vTableBigBlind, vTableBigBlind, StrLen(vTableBigBlind) - InStr(vTableBigBlind,"/$") - 1
   
   
   
            vTableType := substr(vTableArray4,1,2)                                                 ; get the table type (NL, PL, FL) which is the first 2 characters of  vTableArray4
            
            ; the table options are also contained in vTableArray4
            ; vTableArray4 consists of 7 characters
            ; NL6ATED
            ; options are
            ; 6 for 6 players
            ; 2 for 2 players
            ; A Antes
            ; D double stack
            ; C capped game
            ; E educational table
            ; T speed  NOTE: we use "S" in our options for this to make it easier for the user to remember speed
            
            ; Note that we concatenate these options in alphabetical order, so that if full tilt added some other options together, we'll list them in alphabetical order.
            
            vTableOptions := ""
            if instr(vTableArray4,"A",1)
               vTableOptions := vTableOptions . "A"
            if instr(vTableArray4,"C",1)
               vTableOptions := vTableOptions . "C"
            if instr(vTableArray4,"D",1)
               vTableOptions := vTableOptions . "D"
            if instr(vTableArray4,"E",1)
               vTableOptions := vTableOptions . "E"
            if instr(vTableArray4,"T",1)
               vTableOptions := vTableOptions . "S"                  ; Note we substitute and S for the T that full tilts uses for the speed tables
               
            ; if there weren't any of these options, then we set vTableOptions to none
            if NOT vTableOptions
               vTableOptions := "None"
               
               
            ; remove the happy hour string from the players string if it is there
            StringReplace, vTableArray5, vTableArray5,%A_Space%H,,All            
            
            StringLeft, vTableNumPlayers, vTableArray5, 1                              ; get the number of players at table
            StringRight, vTableNumSeats, vTableArray5, 1                               ; get num of seats at table
            vTableWaitNum := vTableArray6                                              ; get num of players in wait list
            StringRight, vTableAvgPot, vTableArray7, StrLen(vTableArray7) - 1          ; get the avg pot size
            StringLeft, vTablePlyrPerFlop, vTableArray8, StrLen(vTableArray8) - 1          ; get the % players per flop
            vTableHandsPerHour := vTableArray9                                       ; get the number of hands per hour
            StringReplace, vTableHandsPerHour, vTableHandsPerHour,>,,All                ; if there is a > char in there, then replace it with NULL     
   


            ; if any of these table parameters are blank, then set them equal to the desired so that we make a match below
            if (vTableWaitNum == "")
               vTableWaitNum := DesiredMaxWaitNum%vThisGroup%
            if (vTableAvgPot == "")
               vTableAvgPot := DesiredMinPot%vThisGroup%
            if (vTablePlyrPerFlop == "")
               vTablePlyrPerFlop := DesiredMinPlyrperFlop%vThisGroup%
            if (vTableHandsPerHour == "")
               vTableHandsPerHour := DesiredMinHandsPerHour%vThisGroup%




;outputdebug,  TableName=%vTableName%`nstakes=%vTableBigBlind%`ntype=%vTableType%`noptions=%vTableOptions%`n#players=%vTableNumPlayers%`nseats=%vTableNumSeats%`navgpot=%vTableAvgPot%`nPlyrs/pot=%vTablePlyrPerFlop%`nhands/hr=%vTableHandsPerHour%`n


            ; in version 1.13 I removed the possibility of having options for None or Deep...  as this is when Full Tilt added a number of options to their tables
   
            ; check that we open a table with the desired criteria, 
            ;       AND it is not in the block table name list
            ;       AND it does not already exist
            ;       AND it is not open in another user area
            If (      (!WinExist(vTableName))
                  AND (vTableBigBlind == DesiredBigBlind%vThisGroup%)
                  AND (vTableType == DesiredType%vThisGroup%)
                  AND (vTableOptions == DesiredOptions%vThisGroup%)
                  AND (vTableNumPlayers >= DesiredMinNumPlayers%vThisGroup%)
                  AND (vTableNumPlayers <= DesiredMaxNumPlayers%vThisGroup%)
                  AND (vTableNumSeats == DesiredNumSeats%vThisGroup%)
                  AND (vTableWaitNum <= DesiredMaxWaitNum%vThisGroup%)
                  AND (vTableAvgPot >= DesiredMinPot%vThisGroup%)   
                  AND (vTablePlyrPerFlop >= DesiredMinPlyrperFlop%vThisGroup%)
                  AND (vTableHandsPerHour >= DesiredMinHandsPerHour%vThisGroup%)  
                  AND (!InStr(BlockTableNameList,vTableName,1))
                  AND (!CheckIfTableisOpenInOtherUserArea(vTableName))        )
            {


            ;outputdebug,  TableName=%vTableName%`nstakes=%vTableBigBlind%`ntype=%vTableType%`noptions=%vTableOptions%`n#players=%vTableNumPlayers%`nseats=%vTableNumSeats%`navgpot=%vTableAvgPot%`nPlyrs/pot=%vTablePlyrPerFlop%`nhands/hr=%vTableHandsPerHour%`n

   
               ; check that the table is already open in our area, skip it if it is
               ;IfWinExist %vTableName%
               ;   continue
   
               ; check that the table is open in another user area on this computer
               ;if (CheckIfTableisOpenInOtherUserArea(vTableName) == 1)
               ;   continue
   
   
               ; we have a table that we would like to open
               ; check if we have max number of tables open
               ; check if we have a table open in a lower priority group that we could close, if so close it
               ; if we closed a table, then continue on to open this table
   

               ;  need to see if we need to close a table first   ??????????????????????????? what if more tables are open
               ;  if (NumTablesOpen >= MaxNumTables)
               
               
               ; if we already have the max number of tables open, then see if we can close one in another group
               
               If  (NumTablesOpenInGroups == MaxNumTablesInGroups)
               {
                  ; if we can't close a table, then break out of trying for this group
                  if ( ! CloseTableInOtherGroup(vThisGroup))
                     break 
                  else
                     UpdateNumTablesOpen()                     ; update totals since we closed a table
               }
            
               ; if we already have the max number of tables open possible, then break out of this
               if (NumTablesOpen >= MaxNumTables) OR (NumTablesOpenInGroups >= MaxNumTablesInGroups)
                  break
                  

               
               ; ok, we should be able to open a table
   
               ; OK, we have the name of the table we want to open
               ; Loop until we open the table, or the table dissappears
               Loop
               {
                  ; get the current "focused" position that we are at in the lobby
                  ControlGet, vFocusedPos, list, Count Focused, SysListView%SysListViewNum%, ahk_id%vLobbyId%
                  
                  
                  
                  ; read the entire lobby table list again, so we can find the position of the table we need
                  ControlGet, vLobbyTableString1, List,, SysListView%SysListViewNum%, ahk_id%vLobbyId%
                  ; Loop thru all the names of the Table name list looking for the positon of our table
                  vTablePos := 0
                  Loop, Parse, vLobbyTableString1, `n
                  {
                     if (vTableData == A_LoopField)
                     {
                        vTablePos := A_index
                        break
                     }
                  }
                  


                  ; check if our table was found in the list, if not set disappeared flag and break
                  if (NOT vTablePos)
                  {
                     break
                  }
                  ; we found the table position...
                  ; find out how far we have to move the focused position in the lobby
                  vFocusedOffset := vTablePos - vFocusedPos
   
                  ;msgbox vTablePos=%vTablePos%`nvFocusedPos=%vFocusedPos%`nvFocusedOffset=%vFocusedOffset%
   
   
                  ; if vFocusedOffset is positive, then we need to move down the list
                  if (vFocusedOffset > 0)
                  {
                     ; pagedown once for every 17
                     Loop, % vFocusedOffset // 17
                        ControlSend, SysListView%SysListViewNum%, {Blind}{PgDn}, ahk_id%vLobbyId%
                     ; down once for every modulo remainder
                     Loop, % mod(vFocusedOffset, 17)
                        ControlSend, SysListView%SysListViewNum%, {Blind}{Down}, ahk_id%vLobbyId%
                  }
                  ; else if it is negative, then we need to move up the list
                  else if (vFocusedOffset < 0)
                  {
                     vFocusedOffset := -vFocusedOffset
                     ; pageup once for every 17
                     Loop, % vFocusedOffset // 17
                        ControlSend, SysListView%SysListViewNum%, {Blind}{PgUp}, ahk_id%vLobbyId%
                     ; up once for every modulo remainder
                     Loop, % mod(vFocusedOffset, 17)
                        ControlSend, SysListView%SysListViewNum%, {Blind}{Up}, ahk_id%vLobbyId%
                  }
   
                  ; small time delay to allow the full tilt table to catch up
                  sleep, 75
   
                  ; we should be focused on the proper table in the list...
                  ; but need to check it, in case the table list has changed, which it
                  ; often does.
   
                  ; get the data of the table that we are focused on in the lobby
                  ControlGet, vFocusedTableData, list, Focused, SysListView%SysListViewNum%, ahk_id%vLobbyId%
;                  StringTrimLeft, vFocusedTableName, vFocusedTableName, InStr(vFocusedTableName, "`t")
;                  StringMid, vFocusedTableName, vFocusedTableName, 1, InStr(vFocusedTableName, "`t")-1
;outputdebug,  vFocusedTableData=%vFocusedTableData%    vTableData=%vTableData%
                  ; if the vFocusedTableData matches the data of the table we wanted to open, then open that table
                  if (vFocusedTableData == vTableData)
                  {
   
   
                     ; check one more time that this table is not open in another user area...
                     ; if it is NOT open in another area, then open it here
   
                     if (CheckIfTableisOpenInOtherUserArea(vTableName) == 0)
                     {
   
                        ; save the last open window, to activate it after this minimizing
;                        vLastWinId := WinActive("A")   

                        

                        ; read the player's names and stack sizes for this table
                        ; loop for up to 3 seconds until this data is available
                        loop, 150
                        {
                           sleep, 20
                           ControlGet, vPlayerListWindow, List,, SysListView321, ahk_id%vLobbyId%
                           if (vPlayerListWindow <> "")
                              break
         
                        }                 
                        
                        ; if the list window is still blank, then break out, as we can't seem to get the player's names
                        
                        ; make comma delimited list of players and stacks already seated at this table
                        vPlayerList := ""
                        vStackList := ""
                        Loop, Parse, vPlayerListWindow, `n
                        {
                           ; break this next line into an array, so we can get the player's name, in array element 3
                           StringSplit, vPlayerListFields, A_LoopField, %A_Tab%
                           ;for some reason FT now puts 1 weird character in the name field for each player... need to strip off the first character
                           StringTrimLeft, vPlayerListFields2, vPlayerListFields2, 1
                           
                           ; remove the $ from the beginning of the stack size
                           StringTrimLeft, vPlayerListFields3, vPlayerListFields3, 1
                           
                           ; remove any commas from the stack size
                           StringReplace, vPlayerListFields3, vPlayerListFields3,`,,,All
                           
                           
                           vPlayerList := AddItemToList(vPlayerList,vPlayerListFields2)
                           vStackList := AddItemToList(vStackList,vPlayerListFields3)
                        }          
                        
                        
                        ;outputdebug, Players=%vPlayerList%    Stacks=%vStackList%   
                        ;return             
                        

                        ; count the number of short stacks (and/or players) at table
                        ; get the number of stacks in list
                        vNumStacks := GetNumItemsInList(vStackList)
                        
                        ; check if the max number of short stacks is < num of seats at the table, so that we have to read the player list to get the # of short stacks
                        if (DesiredMaxNumShortStacks%vThisGroup% < vTableNumSeats)
                        {
                           ; get the number of short stacks in the list
                           vNumShortStacks := 0
                           Loop, % vNumStacks
                           {
                              vStackSize := GetItemNFromList(vStackList,A_Index)
                              ; see if this stack is a short stack... but make sure the player has more than 0 (and he might be sitting out)
                              if (((vStackSize/vTableBigBlind) <= ShortStackSizeBB) AND (vStackSize > 0))
                                 vNumShortStacks++
                           }

                           ;outputdebug, Number of shortstacks=%vNumShortStacks%   
                           
                           ; if the number of short stacks is > the criteria setting, then BREAK out of this loop, as this table does not meet criteria
                           if (vNumShortStacks > DesiredMaxNumShortStacks%vThisGroup%)
                           {
                              break
                           }  
                        }   
                     
                     

                        

                        if SharkListEnabled
                        {
                           ; check if we are enable to check for sharks
                           vFoundSharkFlag := 0
                           ; check if there are any sharks at table, and if so, do not open this table
                           ; loop to get each player at this table...   then see if that player is at the table
                           Loop, % vNumStacks
                           {
                              vPlayer := GetItemNFromList(vPlayerList,A_Index)
                              
                              if (instr(SharkList,vPlayer,1))
                              {
                                 ;outputdebug, Player=%vPlayer%  is on the SharkList
                                 vFoundSharkFlag := 1
                                 break
                              }   
                           }  
                           ; if we found a shark, then break out of this loop that is trying to open this particular table
                           if vFoundSharkFlag
                              break
                           
                        }


   
                        ; open this table
                        ControlSend, SysListView%SysListViewNum%, {Blind}{Enter}, ahk_id%vLobbyId%
;outputdebug, waiting for %vTableName% to open
                        ; wait for the table to appear,
                        WinWait, %vTableName% ,,WinOpenTime
                        if MinimizeTablesFlag
                           WinMinimize, %vTableName% ahk_group GroupTableName
;outputdebug, %vTableName% is open
;                        WinActivate, ahk_id%vLastWinId%
 
 
                        ; Update the table names since we opened one (need to do this here so that other
                        ;     user areas don't open up the same tables)
                        RefreshNames()
   
                        ; find out how may tables are currently open in each group
                        ;UpdateNumTablesOpen()
                        ; show the number of tables open now
;outputdebug, in OpenTables 3
                        DisplayStatus("Opening Tables")
;outputdebug, in OpenTables 4
                        break
                     }
                  }
                  ; we are still not focused on the desired table... start this loop over and try again
                  ; the table list must have changed while we were doing this operation.
   
               }                          ; end of loop to open the table in the list
            }                             ; end of IF for a valid table we found
         }                                ; end of Loop, Parsing table list
      }                                   ; end of Loop, NumGroups
   }                                      ; end of Loop, 2   for the 2 passes

   ; move back to the top of the Lobby list box
   ;ControlSend, SysListView%SysListViewNum%, {Blind}{HOME}, ahk_id%vLobbyId%

   ; minimize the lobby if user's flag is set
   if MinimizeLobbyFlag
      PostMessage, 0x112, 0xF020,,,ahk_class FTCLobby              ;        WinMinimize, ahk_group GroupLobbyName

   ; Update the table names, if we opened any new ones
   RefreshNames()


    ; find out how may tables are currently open in each group
   ;UpdateNumTablesOpen()


;outputdebug, in OpenTables 5
   ; set and display our current status
   if TimerEnabledFlag
      DisplayStatus("Waiting For Timer")
   else
      DisplayStatus("Stopped")
;outputdebug, in OpenTables 6
; reactivate the last active window
WinActivate, ahk_id%vLastWinId%

}

; -------------------------------------------------------------------------------------------------------
; Find the number of tables open in each group
UpdateNumTablesOpen()
{
   ; make all global vars available in the functions
   global
   ; define local variables here
   local vLobbyId, vTableIdList, vLobbyTableString, vTableId, vTableName
   local vTablePosInString, vTablePosInString1, vTableBigBlind, vTableType, vTableOptions
   local vTableNumSeats, vTempType, vTitleBigBlind
   
   
;outputdebug, in UpdateNumTablesOpen()
   
   ; remove any tables that have been on the block table list too long
   BlockTableListUpdate()

   ; get the Lobby ID, incase the lobby has been closed an re-opened since last time
   ;WinGet, vLobbyId, ID, ahk_group GroupLobbyName                       ; get the lobby ID
   WinGet, vLobbyId, ID, ahk_class FTCLobby
   ; get the total number of tables open
   WinGet, NumTablesOpen, List, ahk_group GroupTableName



   ; reset the number of tables in each group to 0, as we will be counting them in this sub
   Loop, %NumGroups%
   {
      NumTablesOpen%A_index% := 0
   }

   NumTablesOpenInGroups := 0


   ;make a list of all the open table IDs, excluding Lobby
   ;WinGet puts the table count in the variable TableIdList,
   WinGet, vTableIdList, List, ahk_group GroupTableName

   ;read in the entire Lobby table list into a string...  so we can see if our tables are still open in lobby
   ControlGet, vLobbyTableString, List,, SysListView%SysListViewNum%, ahk_id%vLobbyId%

;outputdebug, %vLobbyTableString%
   ; loop through all of the open tables
   Loop, %vTableIdList%
   {
   
      ; find the next ID of the next open table
      StringTrimRight, vTableId, vTableIdList%A_Index%, 0

      ; if this table no longer exists... then continue to next table
      IfWinNotExist, ahk_id%vTableId%
         continue


      ; get the value of the big blind from the Title Bar
      vTitleBigBlind := TableBigBlind(vTableId)

      ; we surround the table name in tab characters, so that we are checking the full name, and not part of the name (in the instr() function one line down)
      vTableName := "`t" . TableRingName(vTableId) . "`t"

      ; we will start looking in the string starting at the first position (we add one to it later)
      vTablePosInString := 0
      
      
      ; it is possible that there can two tables with the same name in the vLobbyTableString
      ; we assume that they wouldn't have the same big blind value
      ; so we will loop thru the entire vLobbyTableString looking for the vTableName with the blind the same as our title bar big blind: vTitleBigBlind
      ; we add 1 to the starting position, so that we don't find the previous occurrance of the table name
      while (vTablePosInString := InStr(vLobbyTableString, vTableName,1,vTablePosInString + 1))
      {
;outputdebug, stuck in the while      %vTablePosInString%      %vTableName%
         ; we now need to extract the Stakes, Type, Options and NumberSeats from the string
         ;     to see if they match one of our groups, so we can count it.

         ; extract the Stakes (actually only the big blind amount)
         ; find the position of the next tab char
         vTablePosInString := InStr(vLobbyTableString,"`t",0, vTablePosInString)
         ; find the position of the /$
         vTablePosInString := InStr(vLobbyTableString,"/$",0, vTablePosInString)
         ; and get the next position of the tab char
         vTablePosInString1 := InStr(vLobbyTableString,"`t",0,vTablePosInString)
         ; The Stakes (the big blind amount) are inbetween the /$ and the next tab character
         StringMid, vTableBigBlind, vLobbyTableString, vTablePosInString + 2, vTablePosInString1 - vTablePosInString - 2

         ; if the big blind for this table is different from our title bar, then continue on
         if (vTitleBigBlind != vTableBigBlind)
            continue

         ; extract the entire Type string, which contains the type and options
         ; set the position to the 1st character of the TYPE
         vTablePosInString := vTablePosInString1 + 1
         ; and get the next position of the tab char
         vTablePosInString1 := InStr(vLobbyTableString,"`t",0,vTablePosInString)
         ; get the entire type string (which contains type and options)
         vTempType := substr(vLobbyTableString,vTablePosInString,vTablePosInString1 - vTablePosInString)
         

         vTableType := substr(vTempType,1,2)                                                 ; get the table type (NL, PL, FL) which is the first 2 characters of  vTempType

         ; the table options are also contained in vTempType
         ; vTempType consists of 7 characters
         ; NL6ATED
         ; options are
         ; 6 for 6 players
         ; 2 for 2 players
         ; A Antes
         ; D double stack
         ; C capped game
         ; E educational table
         ; T speed  NOTE: we use "S" in our options for this to make it easier for the user to remember speed

         ; Note that we concatenate these options in alphabetical order, so that if full tilt added some other options together, we'll list them in alphabetical order.

         vTableOptions := ""
         if instr(vTempType,"A",1)
            vTableOptions := vTableOptions . "A"
         if instr(vTempType,"C",1)
            vTableOptions := vTableOptions . "C"
         if instr(vTempType,"D",1)
            vTableOptions := vTableOptions . "D"
         if instr(vTempType,"E",1)
            vTableOptions := vTableOptions . "E"
         if instr(vTempType,"T",1)
            vTableOptions := vTableOptions . "S"                  ; Note we substitute and S for the T that full tilts uses for the speed tables

         ; if there weren't any of these options, then we set vTableOptions to none
         if NOT vTableOptions
            vTableOptions := "None"





         ; extract the Num Seats for this table
         ; We need to move over to the next "/" character, after which is where the number of seats
         vTablePosInString := InStr(vLobbyTableString,"/",0,vTablePosInString)

         ; extract the number of seats at this table
         StringMid, vTableNumSeats, vLobbyTableString, vTablePosInString +1, 1


;outputdebug,  TableName=%vTableName%..stakes=%vTableBigBlind%..type=%vTableType%..Options=%vTableOptions%..seats=%vTableNumSeats%..NumGroups=%vNumGroups%

         ; removed this below in version 1.13 -->         AND ((vTableOptions == DesiredOptions%A_index%)   OR (DesiredOptions%A_index% == "All"))

         ; loop through the groups, and see if there is a match... if so, increment that group's table count
         ;    and the group is active with EnabledGroup ==  1
         Loop, %NumGroups%
         {

            If (      (vTableBigBlind == DesiredBigBlind%A_index%)
                  AND (vTableType == DesiredType%A_index%)
                  AND (vTableOptions == DesiredOptions%A_index%)
                  AND (vTableNumSeats == DesiredNumSeats%A_index%)
                  AND (EnabledGroup%A_Index%)       )
            {
               NumTablesOpen%A_index%++
               NumTablesOpenInGroups++
            }
         }
      }                       ; end of the WHILE
   }
}


; -------------------------------------------------------------------------------------------------------

; check if the hero is seated
HeroSeated(pWinId)
{
   local vPixD, vTX, vTY
      ; now look for some white text around the "get chips" button

      ; Find the target position to look
      vPixD := 10              ; look for check mark in +- 10 pixel area on a large table
      vTX := 25
      vTY := 43
      ; scale these dimensions and find the screen position of this item
      ScreenPosScaled(vTX,vTY,vPixD,pWinId,1)
      CoordMode,Pixel,Screen
      ; search for a black part of a check mark
      PixelSearch,,,vTX - vPixD, vTY - vPixD, vTX + vPixD, vTY + vPixD, 0xFFFFFF
      If NOT Errorlevel
         return 1
      else
         return 0

}


; *******************************************************************************
; -------------------------------------------------------------------------------
; Screen Functions
; -------------------------------------------------------------------------------
; *******************************************************************************


; this function scales pPosX,pPosY for the current table size, and adds in the screen position
;     vPosY is assumed to include the default title bar height of 26
;     If the title bar is different than 26, it will correct for this.
; pDelta is scaled up or down by the amount of change in the X dimension of the table
;        this is typically used to scale the pixel search area, depending on the table size.
; if pType = 0, then return position relative to the active table
; if pType = 1, then return position relative to the screen
ScreenPosScaled(ByRef pPosX, ByRef pPosY, ByRef pDelta, pWinId, pType)
{
   local vTBH, vX, vY, vW, vH

   ; get the title bar height for this window
   SysGet, vTBH, 4


   ; get the xy position and size of this table
   WinGetPos, vX, vY,vW,vH,ahk_id%pWinId%

   ; scale the pixel delta search area
   pDelta := Round((vW / 802) * pDelta)

   ; if pType == 1, then get the screen postion
   if (pType)
   {
      ; default table size is 802,581  including default title bar size of 26
      ; find the screen position of these coordinates (vPosX,vPosY), scaled for a new table size vX,vY
      pPosX := Round(vX + (vW / 802) * pPosX)
      pPosY := Round(vY + ((vH - vTBH) / (581-26)) * (pPosY - 26) + vTBH)
   }
   ; else get the position to the table
   else
   {
      ; default table size is 802,581  including default title bar size of 26
      ; find the screen position of these coordinates (vPosX,vPosY), scaled for a new table size vX,vY
      pPosX := Round((vW / 802) * pPosX)
      pPosY := Round(((vH - vTBH) / (581-26)) * (pPosY - 26) + vTBH)
   }
   ; these values are returned back to caller by reference

}
; -------------------------------------------------------------------------------------------------------


RefreshNames()
{
   ; make all global vars available in the functions
   ; none

   ;locally used variables (begin with "v")
   local vOldList, vIdList, vWindow, vString, vStringArray


   ; We don't want the other copies interfering while we do this...
   BeginCriticalCode()

   ; Read in everythig that was in the old Settings\ftto.tablelist
   FileRead, vOldList, Settings\ftto.tablelist

   ; Delete the old copy of TableList (if it exists).
   FileDelete, Settings\ftto.tablelist

   ; Save all the lines which are not our's back to the file.
   Loop, Parse, vOldList, `r`n  ; Rows are delimited by linefeeds (`n).
   {
      if StrLen(A_LoopField)>0
      {
         IfNotInString, A_LoopField, %A_UserName%.%A_ComputerName%
         FileAppend , %A_LoopField%`r`n, Settings\ftto.tablelist
      }
   }


   WinGet, vIdList, List, ahk_group GroupTableName
   Loop, %vIdList%
   {
      StringTrimRight, vWindow, vIdList%A_Index%, 0
      WinGetTitle, vString, ahk_id%vWindow%
      StringSplit, vStringArray, vString, -
      StringTrimRight, vStringArray1, vStringArray1, 1
      FileAppend , %A_UserName%.%A_ComputerName%:%vStringArray1%`r`n, Settings\ftto.tablelist
   }

   ; Other copies can run now if they need to.
   EndCriticalCode()

}

; -------------------------------------------------------------------------------------------------------

; Check if TableName is open in another USER area of this computer
; A file is kept of all the tables open on this computer (called Settings\ftto.tablelist)
CheckIfTableisOpenInOtherUserArea(pThisTableName)
{
   ; define local variables
   local vCurrentTableList

   ; We don't want the other instances writing to the table list when we read it next
   BeginCriticalCode()

   ; Read the current list of used tables.
   FileRead, vCurrentTableList, Settings\ftto.tablelist


   ; Other copies can run now if they need to.
   EndCriticalCode()

   ; loop through all the table names in the Settings\ftto.tablelist file
   Loop, Parse, vCurrentTableList, `r`n  ; Rows are delimited by linefeeds (`n).
   {


      if StrLen(A_LoopField)>0
      {
         ; check that the name is NOT in THISUSER.THISCOMPUTER
         IfNotInString, A_LoopField, %A_UserName%.%A_ComputerName%
         {


            ; check if the TableName is part of another user
            IfInString, A_LoopField, %pThisTableName%
            {

               ; Other copies can run now if they need to.
               EndCriticalCode()
               ; return 1, indicating that we found a table belonging to another user
               return, 1
            }
         }
      }
   }


   ; we did not find any matches
   return, 0 ; Not found.
}



; -------------------------------------------------------------------------------------------------------

; When we are reading an writing to files that other instances of this program
;     could also be reading and writing to, we need to set a flag (Settings\ftto.semaphore)
;     to indicate that we need to have exclusive access for a while.
BeginCriticalCode()
{
   ; define local variables
   local vCounter

   vCounter := 0
   Loop
   {
      ; if the file Settings\ftto.semaphore does NOT exist, then break
      IfNotExist, Settings\ftto.semaphore
         Break
      ; Settings\ftto.semaphore does exist, so wait a sec and try again
      Sleep, 1000
      vCounter := vCounter + 1
      ; if Settings\ftto.semaphore still exists after consequitive 5 seconds, we must have a lock up condition...  so just erase it
      ;     it should not have taken this long for this program in another area to get writing/reading the Settings\ftto.tablelist file
      if vCounter >= 5
         FileDelete, Settings\ftto.semaphore
   }
   ; Settings\ftto.semaphore does not exist, so create it so we have exclusive access
   FileAppend, semaphore in use, Settings\ftto.semaphore
   return
}

; -------------------------------------------------------------------------------------------------------

; When we are done with our critical sections of code, erase the Settings\ftto.semaphore
EndCriticalCode()
{
   ; define local variables
   ; none
   FileDelete, Settings\ftto.semaphore
   return
}


;====================================================================================================================


; reads the title bar of table pWinId, and returns the big blind
TableBigBlind(pWinId)
{
   global
   local vWinTitle, vPos0, vPos1, vPos2, vPos3, Ante, SmallBlind, BigBlind

   ; need to find the amount of the small blind and big blind...   read the title and extract the info
   WinGetTitle, vWinTitle, ahk_id%pWinId%

   Ante := 0

   ; read the small blind and big blind from the window title

   ; check if this is a play money cash game
   If (InStr(vWinTitle, "Play Chip") AND (NOT InStr(vWinTitle,"Play Chip Tournament")))
   {
      ; find the first -
      vPos1 := InStr(vWinTitle," - ")
      ; find the position of /
      vPos2 := Instr(vWinTitle, "/")
      ; find the position of the " - " after the big blind
      vPos3 := InStr(vWinTitle, " - ", 0 , vPos2)
      StringMid, SmallBlind, vWinTitle, vPos1 + 3, vPos2 - vPos1 - 3
      StringMid, BigBlind,   vWinTitle, vPos2 + 1, vPos3 - vPos2 - 1
   }
   ; check if this is a real money cash game
   ; cash games have "/$ in them"
   else If InStr(vWinTitle, "/$")
   {
      ; find the first $
      vPos1 := InStr(vWinTitle,"$")
      ; find the position of /$
      vPos2 := Instr(vWinTitle, "/$")
      ; find the position of the - after the big blind
      vPos3 := InStr(vWinTitle, "-",0,vPos2)
      StringMid, SmallBlind, vWinTitle, vPos1 + 1, vPos2 - vPos1 -1
      StringMid, BigBlind, vWinTitle, vPos2 + 2, vPos3 - vPos2 - 2
   }
   ; else this must be a tournament
   ; check if there are antes in this must be a tournament.
   else if InStr(vWinTitle," Ante ")
   {
      ; find the )
      vPos0 := InStr(vWinTitle,")")
      ; find the first - after the )
      vPos1 := InStr(vWinTitle," - ", 0, vPos0)
      ; find the position of / after the -
      vPos2 := Instr(vWinTitle, "/", 0, vPos1)
      ; find the position of the word "Ante" after the big blind
      vPos3 := InStr(vWinTitle, "Ante", 0 , vPos2)
      ; find the position of " - " after the word Ante
      vPos4 := InStr(vWinTitle, " - ", 0 , vPos3)
      StringMid, SmallBlind, vWinTitle, vPos1 + 3, vPos2 - vPos1 - 3
      StringMid, BigBlind, vWinTitle, vPos2 + 1, vPos3 - vPos2 - 1
      StringMid, Ante, vWinTitle, vPos3 + 5, vPos4 - vPos3 - 5
   }
   ; else there are not antes
   else
   {
      ; find the )
      vPos0 := InStr(vWinTitle,")")
      ; find the first - after the )
      vPos1 := InStr(vWinTitle," - ", 0, vPos0)
      ; find the position of /
      vPos2 := Instr(vWinTitle, "/")
      ; find the position of the " - " after the big blind
      vPos3 := InStr(vWinTitle, " - ", 0 , vPos2)
      StringMid, SmallBlind, vWinTitle, vPos1 + 3, vPos2 - vPos1 - 3
      StringMid, BigBlind,   vWinTitle, vPos2 + 1, vPos3 - vPos2 - 1
   }


return BigBlind

}


; -----------------------------------------------------------------------------------------

; reads the title bar of pWinId, and returns the tournament ID
;        returns "" if not found (ring game)
TableTournamentId(pWinId)
{
   global
   local vWinTitle, vPos1, vPos2, vId, vWinId
   
   
   ; need to find the amount of the small blind and big blind...   read the title and extract the info
   WinGetTitle, vWinTitle, ahk_id%pWinId%

   vID := ""

   ; get the tourney ID between the parenthiesis (xxxxxxxxx)
   If InStr(vWinTitle, "(")
   {
      ; find the ( around the id number... skip past the word Turbo, if it exists
      vPos1 := InStr(vWinTitle,"Turbo")
      if vPos1
      {
         vPos1 := InStr(vWinTitle,"(",0, vPos1)
         vPos2 := Instr(vWinTitle, ")",0, vPos1)
      }
      else
      {  
         vPos1 := InStr(vWinTitle,"(")
         vPos2 := Instr(vWinTitle, ")")
      }   

      ; read the contents between the ()
      StringMid, vId, vWinTitle, vPos1 + 1, vPos2 - vPos1 -1
   }
   
   Return vId
}

; -------------------------------------------------------------------------------------

; returns Ring=1 Tourney=0
TableRingOrTournament(pWinId)
{
   local vWinTitle
   ; need to find the amount of the small blind and big blind...   read the title and extract the info
   WinGetTitle, vWinTitle, ahk_id%pWinId%
   
   If InStr(vWinTitle, "Play Money Sit & Go")
      return 0  
      
   If InStr(vWinTitle, "Play Chip Tournament")
      return 0    
      
   If InStr(vWinTitle, "Play Chip")
      return 1       

   ; cash games have "/$" in the title
   If InStr(vWinTitle, "/$")
      return 1
   else
      return 0
}


; -----------------------------------------------------------------------------------------

; reads the title bar of pWinId, and returns the Ring Table's Name
;        returns "" if not found (tournament game)
TableRingName(pWinId)
{
   local vTableName
   
   if (! TableRingOrTournament(pWinId))
      return ""

   ; get the name of the next open table
   WinGetTitle, vTableName, ahk_id%pWinId%
   StringLeft, vTableName, vTableName, InStr(vTableName,"-") - 2    ; strip off all but just table name
   
   ; if there is a (  in the name...   remove everything after the last character of the actual table name...  including 1 character before the (    )
   vPos := Instr(vTableName, "(")
   if vPos
   {
      StringLeft, vTableName, vTableName, vPos - 2    ; strip off all but just table name
   }
   
   
   Return vTableName
}

;###########################################
;################# Lists ####################
;###########################################

; code by Roland

;adds "item" to the end of "list"
;returns:  the NEW list (if list is not NULL. if it is null, then the item is returned)
;paramters:
;     list: the current list before something is added
;     item: the item to be added to the end of the list
;     delimeter: the delimter used in this list...  if not given then a comma is used
AddItemToList(list,item,del="") {
del := IIf(del="",",",del)
If list =
 return item
return list . del . item
}

;return item at said position in said list
; Get item "n" from "list"
GetItemNFromList(list,n=1,del="") {
del := IIf(del,del,",")
StringSplit, item, list, %del%
return item%n%
}

;removes said item from said list
RemoveItemFromList(list,item=1,del="") {
del := IIf(del,del,",")
If InStr(list, item . del)
 return StrRep(list, item . del, "", 0)
else if InStr(list, del . item, "", 0)
 return StrRep(list, del . item, "", 0)
else if (item = list)
 return
else
 return list
}

;removes the nth item from said list
RemoveItemNFromList(list,n,del="") {
del := IIf(del,del,",")
return RemoveItemFromList(list, GetItemNFromList(list,n,del))
}

;returns the number of items in list
GetNumItemsInList(list,del="") {
del := IIf(del,del,",")
StringSplit, array, list, %del%
return array0
}



;returns the position of said item in said list
;(0 if not in list)
GetItemPosInList(list,item,del="") {
del := IIf(del,del,",")
StringSplit, array, list, %del%
Loop %array0% {
        If array%a_index% = %item%
                return a_index
 }
return 0
}

;inserts said item at said position in said list
InsertItemInList(list,item,pos,del="") {
del := IIf(del="",",",del)
StringSplit,array,list,%del%
Loop % IIf( ( pos < array0 ), array0, pos ) {
        thisItem := array%a_index%
        If ( a_index != pos )
                newList = %newList%%del%%thisItem%
        else
                newList = %newList%%del%%item%%del%%thisItem%
 }
If ( InStr(newList, ",",0,0) = StrLen(newList) )
 StringTrimRight, newList, newList, 1
StringTrimLeft, newList, newList, 1
return newList
}

;removes empty items (and trailing delimiters)
CleanList(list, del="") {
If del =
 del = `,
Loop {
  StringReplace, list, list, %del%%del%, %del%, UseErrorLevel
  If ! ErrorLevel
   break
 }
If InStr(list, del) = 1
 StringTrimLeft, list, list, 1
If InStr(list, del,0,0) = StrLen(list)
 StringTrimRight, list, list, 1
return list
}

List_longest(list, del="") {
del := IIf( del="", ",", del)
longest = 0
Loop, Parse, list, %del%
 {
        If (longest < StrLen(a_loopfield))
                longest := StrLen(a_loopfield)
 }
return longest
}

StrRep(str,char,rep_char="",all=1) {
StringReplace,str,str,%char%,%rep_char%,%all%
return str
}

IIf(_boolExpr, _exprTrue, _exprFalse) {
If _boolExpr
 Return _exprTrue
else
 return _exprFalse
}
